Understanding Pepper Programming in Javascript - nao-robot

I've recently started building a Javascript program for Pepper. My goal is to make pepper listen to what people say and either say Hello or make Pepper do an animation based on keyword 'Hello/Animation' in WordRecognized event in Javascript.
As of now,I'm able to show two buttons on the tablet using JavaScript and make Pepper say Hello on one button press and perform animations on another button press. Clicking on the buttons work but I'm not able to make it working for the WordRecognized events by using the Qi Javascript SDK (http://doc.aldebaran.com/2-4/dev/js/index.html ). I went through the link mentioned here and came up with the below code snippet that makes Pepper say Word Detected on hearing the recognized word. Just wondering what else am I missing in the code to make Pepper listen to the words and perform action accordingly?
//Start the Speech Recognition
var asr = session.service('ALSpeechRecognition');
//Define the Vocabulary
vocabulary = ["hello", "dance"];
//Set The Language To English and set the Vocabulary
asr = asr.then( function(asr) { return asr.setLanguage('English') }).then( function(asr){ return asr.setVocabulary(vocabulary, false); } );
console.log("Set the Language to English!");
//Register the Callback function for the Speech REcognition
asr.unsubscribe(); //De-Register if Existing from Before
asr.subscribe();
session.service("ALMemory").then(function (ALMemory) {
ALMemory.subscriber("wordRecognized").then(function (subscriber) {
// subscriber.signal is a signal associated to "wordRecognized"
subscriber.signal.connect(function (state) {
word = state.getData("wordRecognized")[1];
word.then( function() { session.service('ALTextToSpeech').say("A Keyword is Detected!") });
asr.unsubscribe();
}); //subscriber
}); //connect
}); //ALMemory
});

Your code snippet as given won't work, because this:
var asr = session.service('ALSpeechRecognition');
means the asr variable is a future, so you can't call asr.unsubscribe() on it.
You'd have to wrap everything in session.service(...).then(function(asr) { ...} for it to work right, like you do with ALMemory.
The syntax can be a bit awkward, I usually use a small helper library, robotutils.qim.js, that makes the code a bit more readable, and that has a helper for subscribing to ALMemory.

Related

How can I trigger a dialog in Watson Conversation?

I need trigger a specific dialog in ibm-watson conversation, but without ask the user to type something (like a intent). I need to use botkit to init a specific dialog. That's is possible? I'm looking for in all possible documentation and links at Google, but not successfully :/
Sending initial empty message triggers welcome event in the dialog.
To make it do something different, you could set some variable in the context and add condition for that variable to welcome branch in the dialog.
This is how I implemented it in my bot:
function handleHelloEvent(bot, message) {
message.type = 'welcome';
const contextDelta: any = {};
if (message.intent) {
contextDelta.initialIntent = message.intent;
}
//more fields here
watsonMiddleware.sendToWatsonAsync(bot, message, contextDelta).catch((error) => {
message.watsonError = error;
}).then(() => {
//this is the same function which handles message_received events
return handleWatsonResponse(bot, message);
});
}
function handleWatsonResponse(bot, message) {
bot.reply(message, message.watsonData.output.text.join('\n'));
}
controller.on('hello', handleHelloEvent);
controller.on('message_received', handleWatsonResponse);
hello event is specific to webchat/botkit anywhere, you may need to handle different events for different platfoms.
A similar example of code handling welcome event: https://github.com/watson-developer-cloud/botkit-middleware/#dynamic-workspace
(I wrote that one too, so it is a bit too similar).
Dialog example:

Protractor - Unable to access element due to fixed Top navigation bar

I'm facing the following issue in protractor with jasmine
Click/mouse hover not working because of fixed top navigation bar in my application. I need to click/perform mouse hover on a web page.
Unfortunately that element is displaying behind that fixed navigation bar. So scroll till element present & click by x & y coordinates are not working.
My dependencies are :
protractor version 5.2.2
node 8.9.3
selenium standalone 3.13
chrome driver-2.40
chromebrowser v67
OS- Windows 10
Thanks in advance
Try using prototype executeScript
Just try clicking that element from the browser console using id,name or xpath.
For example :
var el = element(by.module('header'));
var tag = browser.executeScript('return arguments[0].click()', el).then(function() {
expect(something).toMatch(something);
});
Another way, along the same lines as what Bharath Kumar S and knowing JeffC's caveat that this approach is cheating, I had a similar issue where the App-Header kept getting in my way of clicking, and I knew I was willing to never need it (so, for instance, to find other ways to navigate or log out and not check for stuff that was on it). I, therefore, did the following, which solved the problem. Note if you refresh the screen, you have to call it again. Also note I am using a number of functions from https://github.com/hetznercloud/protractor-test-helper, which do what you would expect from their names.
var removeAppHeaderIfAny = async function() {
//this function hides the app header
//it is useful to avoid having covers there when Protractor worries that something else will get the click
let found = false;
try {
found = await waitToBeDisplayed(by.className("app-header"), 2000);
} catch (e) {
let s: string = "" + e;
if (s.search("TimeoutError") != 0) flowLog("presumably fine, cover already removed: " + e);
found = false;
}
if (!found) return;
if (found) {
let coverElement = await element(by.className("app-header"));
browser.executeScript(
"arguments[0].style.visibility='hidden';",
coverElement
);
await waitToBeNotDisplayed(by.className("app-header"), 10000);
}
return;
//note after this is called you will not see the item, so you cannot click it
};
As I look at the code, it strikes me one can probably remove the if (found) and associated brackets at the end. But I pasted in something I know has been working, so I am not messing with that.
As indicated up front, I knew I was willing to forego use of the app-header, and it is a bit crude.

How to achieve face detection using web camera

How should I create face detection web application which capture photo and save when face comes in-front of camera.
Which technology currently available to achieve this.
Please Help...
I've been using a wonderful solution called tracking.js (You can find it here). It's simple and wonderful.
Here's an example of how I use it in my code:
var trackerTask;
var tracker = new tracking.ObjectTracker('face');
tracker.setInitialScale(4);
tracker.setStepSize(2);
tracker.setEdgesDensity(0.1);
trackerTask = tracking.track('#vid', tracker, { camera: true })
tracker.on('track', function (event) {
// Do stuff when face was detected
});
// To stop tracking:
setTimeout(function () {
trackerTask.stop();
}, 500);
In the above example, replace #vid with your HTML5 <video> element.

SignalR: How to add client call after the hub is started?

First off, I just started trying to add SignalR 2 to my existing Angular SPA project.
I have a main controller which starts the hub right away that is feeding some messages to the client. Inside, I have several sub pages and each could subscribe to a different hub for services. The problems is that the client doesn't receive message because it is hooked up after the hub is already started in the main controller.
As a test, if I comment out the hub start in the main controller, the one in the sub controller works fine.
From what I read, it is by design that you have to hook up all client calls before starting the hub. I don't understand...if it is a service, I should be able to subscribe or unsubscribe anytime after the hub is started. Why not? How to workaround?
Because no response in the 12 hours (which is quite unusual in so), I had to dig around myself. I think, I was misled by the answers from SO on related questions that you have to subscribe all client call before starting the connection, as mentioned e.g. here. I found in Hubs API Guide, one section says
Define method on client (without the generated proxy, or when adding
after calling the start method)
So, it is possible to add client method after connection is started. The trick is to use so-called "without the generated proxy". That limitation is for "with generated proxy".
The following is my working example taken from SignalR get started tutorial.
This is the main controller using "with generated proxy":
$.connection.statusHub.client.updateStatus = function (status) {
$scope.status = status;
$scope.$apply();
}
$.connection.hub.start();
This is in a subcontroller using "without generated proxy":
var connection = $.hubConnection();
var proxy = connection.createHubProxy('stockTickerHub');
proxy.on('updateStockPrice', function (stock) {
var st = $scope.stocks.firstOfKey(stock.symbol, 'symbol');
st.lastPrice = stock.lastPrice;
$scope.$apply();
});
var hub = $.connection.stockTickerHub;
connection.start().done(function () {
hub.server.getAllStocks().done(function (stocks) {
$scope.stocks = stocks;
});
});
Note that it doesn't work if I use "with generated proxy" in the subcontroller like this:
var hub = $.connection.stockTickerHub;
hub.client.updateStockPrice = function (stock) {
var st = $scope.stocks.firstOfKey(stock.symbol, 'symbol');
st.lastPrice = stock.lastPrice;
$scope.$apply();
};
$.connection.hub.start().done(function () {
hub.server.getAllStocks().done(function (stocks) {
$scope.stocks = stocks;
});
});
To prove the limitation of "with generated proxy" mode, this code works if I comment out the one in the main controller.
By the way, I was so confused by the term with or without generated proxy in the Guide, and in both cases, it is still called xxxProxy. Can't they find a better name? Or somebody has an explanation?

WMS GetFeatureInfo; multiple layers, different sources

I'm developing a web application using GeoExt, OpenLayers and having my own GeoServer to serve various maps. Still, I want to let the user add other WMS's if needed, to be able to play around with all desired layers.
Thus, my problem with the GetFeatureInfo request. Right now I have a toolbar button attached to geoext's map panel,
new GeoExt.Action({
iconCls: "feature",
map: map,
toggleGroup: "tools",
tooltip: "Feature",
control: featureControl
})
its control attribute being
var featureControl = new OpenLayers.Control.WMSGetFeatureInfo({
queryVisible: true,
drillDown: true,
infoFormat:"application/vnd.ogc.gml"
});
I've also defined an event listener to do what I really want once I receive the responses, but that is not relevant here. My problem is the following:
Considering the user clicks on a point where there are 2+ visible layers and at least one of them is from a different source, OpenLayers will have to do one AJAX request per different source and, from OpenLayers own documentation,
Triggered when a GetFeatureInfo response is received. The event
object has a text property with the body of the response (String), a
features property with an array of the parsed features, an xy property
with the position of the mouse click or hover event that triggered the
request, and a request property with the request itself. If drillDown
is set to true and multiple requests were issued to collect feature
info from all layers, text and request will only contain the response
body and request object of the last request.
so, yeah, it will obviously wont work like that right away. Having a look at the debugger I can clearly see that, giving two layers from different sources, it actually DOES the request, it's just that it doesn't wait for the first's response and jumps for the next one (obviously, being asynchronous). I've thought about doing the requests one-by-one, meaning doing the first one as stated above and once it's finished and the response saved, go for the next one. But I'm still getting used to the data structure GeoExt uses.
Is there any API (be it GeoExt or OpenLayers) option/method I'm missing? Any nice workarounds?
Thanks for reading :-)
PS: I'm sorry if I've not been clear enough, english is not my mother tongue. Let me know if something stated above was not clear enough :)
i Hope this help to someone else, I realized that: you're rigth this control make the request in asynchronous mode, but this is ok, no problem with that, the real problem is when the control handle the request and trigger the event "getfeatureinfo" so, i modified 2 methods for this control and it works!, so to do this i declare the control first, and then in the savage mode i modified the methods here is de code:
getInfo = new OpenLayers.Control.WMSGetFeatureInfo({ drillDown:true , queryVisible: true , maxFeatures:100 });
//then i declare a variable that help me to handle more than 1 request.....
getInfo.responses = [];
getInfo.handleResponse=function(xy, request) { var doc = request.responseXML;
if(!doc || !doc.documentElement) { doc = request.responseText; }
var features = this.format.read(doc);
if (this.drillDown === false) {
this.triggerGetFeatureInfo(request, xy, features);
} else {
this._requestCount++;
this._features = (this._features || []).concat(features);
if( this._numRequests > 1){
//if the num of RQ, (I mean more than 1 resource ), i put the Request in array, this is for maybe in a future i could be need other properties or methods from RQ, i dont know.
this.responses.push(request);}
else{
this.responses = request;}
if (this._requestCount === this._numRequests) {
//here i change the code....
//this.triggerGetFeatureInfo(request, xy, this._features.concat());
this.triggerGetFeatureInfo(this.responses, xy, this._features.concat());
delete this._features;
delete this._requestCount;
delete this._numRequests;
// I Adding this when the all info is done 4 reboot
this.responses=[];
}
}
}
getInfo.triggerGetFeatureInfo= function( request , xy , features) {
//finally i added this code for get all request.responseText's
if( isArray( request ) ){
text_rq = '';
for(i in request ){
text_rq += request[i].responseText;
}
}
else{
text_rq = request.responseText;
}
this.events.triggerEvent("getfeatureinfo", {
//text: request.responseText,
text : text_rq,
features: features,
request: request,
xy: xy
});
// Reset the cursor.
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");}
Thanks, you bring me a way for discover my problem and here is the way i solved, i hope this can help to somebody else.
saheka's answer was almost perfect! Congratulations and thank you, I had the same problem, and with it I finally managed to solve it.
What I would change in your code:
isArray() does not work, change it like this: if(request instanceof Array) {...} at the first line of getInfo.triggerGetFeatureInfo()
to show the results in a popup this is the way:
My code:
getInfo.addPopup = function(map, text, xy) {
if(map.popups.length > 0) {
map.removePopup(map.popups[0]);
}
var popup = new OpenLayers.Popup.FramedCloud(
"anything",
map.getLonLatFromPixel(xy),
null,
text,
null,
true
);
map.addPopup(popup);
}
and in the getInfo.triggerGetFeatureInfo() function, after the last line, append:
this.addPopup(map, text_rq, xy);
A GetFeatureInfo request is send as a JavaScript Ajax call to the external server. So, the requests are likely blocked for security reasons. You'll have to send the requests to the external servers by a proxy on your own domain.
Then, configure this proxy in openlayers by setting OpenLayers.ProxyHost to the proper path. For example:
OpenLayers.ProxyHost = "/proxy_script";
See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost for more background information.

Resources