Custom behaviour vs. execute scrypt

Hello,

I wonder when would one use custom behaviour vs. execute script. Should a custom behaviour perform only one single task, or can it be a collection of different tasks? Could you please share your best practices?

Thanks,
-R

Execute scripts are wonderful for when you want to execute a single instance of code once. If you thought you might use that code more than once, or if the behavior is more complex and includes arguments you want to change with each use, then there are certainly advantages to using a custom behavior instead.


1. It can be quicker to use a custom behavior instead of typing up or copying/pasting the same code repeated times for an ExecuteScript behavior.

A simplified example of this can be seen in our tutorial for creating a custom behavior to center Jibo ( seen here). Technically, if you only wanted to center Jibo once something similar could be accomplished by copying and pasting or re-typing this code that uses our centerRobot API:

() => {
  var animate = require("jibo").animate;
  jibo.animate.centerRobot(null, true, null);
}

But if you created a center robot behavior like in our tutorial you could very quickly introduce that centering behavior into your skill without taking the time to re-type or copy/paste.
2. It can allow for an easier way to adjust particular parameters arguments each time

Similar to the above, you could, in many cases, recopy/paste a previously used Executescript and change some of the code to accomplish a result with different arguments/parameters compared to your original Executescript.

But in many cases it may be much easier to define the arguments you want to change on each use of the behavior as seen in part 14 of the tutorial I mentioned earlier.

This would allow you to adjust those particular variables right in the behavior arguments pane instead of digging into the Executescript and editing your code each time:

This can be particular useful if a custom behavior does two or three things but each time you use that behavior you want to change the argument being used for each of those actions.


As a final note, it is worth pointing out that number 1 above (avoiding re-typing or copying/pasting) can also be accomplished by creating a subtree behavior with your execute script as the only behavior in the subtree. You could then call that subtree anytime you wanted to run that script without copying/pasting. Number 2 above (being able to adjust arguments for each use of the repeated behavior) is best accomplished using a custom behavior.

In summary, many custom behaviors could be accomplished using an Executescript one time. But if you want to repeatedly use an action you have custom coded it can often be useful to create a custom behavior especially if there are arguments you want to adjust for each use.

An example of a pre-built custom behavior can be found in behavior 13 of our Sample Code here.

I hope that is helpful!

3 Likes

Thank you John for the very good explanation! I have a few additional questions.

  • What are the best practices with using external JavaScripts js files?
  • Would you recommended to use custom behaviours or execute script instead?
  • Could you please share an example (js and json files) with a custom behaviour having two “function” types?

In general using an external javascript file does not need a custom behavior.

If you are looking to regularly reference an external js file a good practice is to require the file in your skill’s index.js for use later within your skill.

A good example of this can be seen in this skill posted by one of our forum developers, Kevin, demonstrating how Jibo can be used to control Hue light bulbs.

If you take a look at that skill you will notice that at the beginning of the skill’s index.js Kevin requires two js files (application-emitter.js and lighting-controller.js). Later on in the index.js (lines 25-30) he sets those to global blackboard variables.

This allows the js files to be referenced quickly in an ExecuteScript that begins the main.bt for that skill:

In answer to your second, question, it sounds like you are looking for an example of a custom behavior that performs more than one action and has more than one argument that can be changed using the behavior arguments pane. For instance, a custom behavior that causes Jibo to center and allows for controlling the visibility of his eye.

I created a simple example of that by editing the .js and .json files for the center-robot custom behavior that is included in our sample code. I added the following code to the start() section of center-robot.js:

  jibo.animate.setEyeVisible(
          this.options.isVisible
        );

and I added the following code to the "options" section of center-robot.json:

{
                "type": "boolean",
                "field": "isVisible",
                "description": "Make Eye Visible",
                "defaultValue": true
            }

The result is a custom behavior still called CenterRobot but that also contains a Behavior argument (True/False) that allows you to set the visibility of Jibo’s eye as seen in this screen:

For full context I am also pasting the full code of the .js and .json file here.

I hope this is helpful! :slight_smile:

center-robot.js:

"use strict";

let jibo = require('jibo');
let Status = jibo.bt.Status;
let Behavior = jibo.bt.Behavior;

class CenterRobot extends Behavior {
    constructor(options) {
        super(options);
        this.status = Status.INVALID;
    }
    start() {
        this.status = Status.IN_PROGRESS;
        var _this = this;
        jibo.animate.centerRobot(
            jibo.animate.dofs.ALL,
            this.options.isGlobal,
            function() {
                _this.status = Status.SUCCEEDED;
                console.log("test");
              }
        );
        jibo.animate.setEyeVisible(
          this.options.isVisible
        );

        return true;
    }
    update() {
        return this.status;
    }
}

jibo.bt.register('CenterRobot', 'project', CenterRobot);
module.exports = CenterRobot;

and center-robot.json:

{
    "CenterRobot": {
        "description": "Centers Jibo either locally or globally.",
        "type": "leaf",
        "options": [
            {
                "type": "boolean",
                "field": "isGlobal",
                "description": "True to center robot globally. False to center robot locally",
                "defaultValue": false
            },
            {
                "type": "boolean",
                "field": "isVisible",
                "description": "Make Eye Visible",
                "defaultValue": true
            }

        ]
    },
    "meta": {
        "version": 1
    }
}