Пример #1
0
    def testRepeatUntilSucceed(self):
        """Can we repeat a behavior until it succeeds?
        """
        bb = blackboard.Blackboard('test', )  # 'value' defaults to None.
        checker = lambda x: x is not None

        parallel = owyl.parallel
        repeat = owyl.repeatUntilSucceed
        checkBB = blackboard.checkBB
        setBB = blackboard.setBB

        tree = parallel(repeat(checkBB(key='value',
                                       check=checker),
                               final_value=True),

                        # That should fail until this sets the value:
                        owyl.selector(owyl.fail(),
                                      owyl.fail(),
                                      setBB(key='value',
                                            value='foo')),
                        policy=owyl.PARALLEL_SUCCESS.REQUIRE_ALL)

        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)

        # Need to reset the blackboard to get the same results.
        bb = blackboard.Blackboard('test', )  # 'value' defaults to None.
        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)
Пример #2
0
    def testRepeatUntilFail(self):
        """Can we repeat a behavior until it fails?
        """
        bb = blackboard.Blackboard('test', value="foo")
        checker = lambda x: x and True or False  # must eval to True

        parallel = owyl.parallel
        repeat = owyl.repeatUntilFail
        checkBB = blackboard.checkBB
        setBB = blackboard.setBB

        tree = parallel(repeat(checkBB(key='value',
                                            check=checker),
                                    final_value=True),

                        # That should succeed until this sets the value:
                        owyl.selector(owyl.fail(),
                                      owyl.fail(),
                                      setBB(key='value',
                                            value=None)),
                        policy=owyl.PARALLEL_SUCCESS.REQUIRE_ALL)

        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)

        # Need to reset the blackboard to get the same results.
        bb = blackboard.Blackboard('test', value="foo")
        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)
Пример #3
0
    def testRepeatUntilFail(self):
        """Can we repeat a behavior until it fails?
        """
        bb = blackboard.Blackboard('test', value="foo")
        checker = lambda x: x and True or False  # must eval to True

        parallel = owyl.parallel
        repeat = owyl.repeatUntilFail
        checkBB = blackboard.checkBB
        setBB = blackboard.setBB

        tree = parallel(
            repeat(checkBB(key='value', check=checker), final_value=True),

            # That should succeed until this sets the value:
            owyl.selector(owyl.fail(), owyl.fail(),
                          setBB(key='value', value=None)),
            policy=owyl.PARALLEL_SUCCESS.REQUIRE_ALL)

        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)

        # Need to reset the blackboard to get the same results.
        bb = blackboard.Blackboard('test', value="foo")
        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)
Пример #4
0
    def testRepeatUntilSucceed(self):
        """Can we repeat a behavior until it succeeds?
        """
        bb = blackboard.Blackboard('test', )  # 'value' defaults to None.
        checker = lambda x: x is not None

        parallel = owyl.parallel
        repeat = owyl.repeatUntilSucceed
        checkBB = blackboard.checkBB
        setBB = blackboard.setBB

        tree = parallel(
            repeat(checkBB(key='value', check=checker), final_value=True),

            # That should fail until this sets the value:
            owyl.selector(owyl.fail(), owyl.fail(),
                          setBB(key='value', value='foo')),
            policy=owyl.PARALLEL_SUCCESS.REQUIRE_ALL)

        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)

        # Need to reset the blackboard to get the same results.
        bb = blackboard.Blackboard('test', )  # 'value' defaults to None.
        v = owyl.visit(tree, blackboard=bb)
        results = [x for x in v]
        result = results[-1]
        self.assertEqual(result, True)
Пример #5
0
    def testVisitSelectorFailure(self):
        """Can we visit a failing selector?
        """
        tree = owyl.selector(owyl.fail(), owyl.fail(), owyl.fail())

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, False, False])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, False, False])
Пример #6
0
    def testVisitSelectorSuccess(self):
        """Can we visit a successful selector?
        """
        tree = owyl.selector(owyl.fail(), owyl.fail(), owyl.succeed(),
                             owyl.fail())

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, True, True])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, True, True])
Пример #7
0
    def testParallel_OneSucceeds_Failure(self):
        """Can we visit a failing parallel (one succeeds)?
        """
        tree = owyl.parallel(owyl.sequence(owyl.fail(), owyl.fail()),
                             owyl.sequence(owyl.fail(), owyl.fail()),
                             policy=owyl.PARALLEL_SUCCESS.REQUIRE_ONE)
        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False])
Пример #8
0
    def testVisitSelectorFailure(self):
        """Can we visit a failing selector?
        """
        tree = owyl.selector(owyl.fail(),
                             owyl.fail(),
                             owyl.fail())

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, False, False])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, False, False])
Пример #9
0
    def testVisitSelectorSuccess(self):
        """Can we visit a successful selector?
        """
        tree = owyl.selector(owyl.fail(),
                             owyl.fail(),
                             owyl.succeed(),
                             owyl.fail())

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, True, True])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False, False, True, True])
Пример #10
0
    def testParallel_OneSucceeds_Failure(self):
        """Can we visit a failing parallel (one succeeds)?
        """
        tree = owyl.parallel(owyl.sequence(owyl.fail(),
                                           owyl.fail()),
                             owyl.sequence(owyl.fail(),
                                           owyl.fail()),
                             policy=owyl.PARALLEL_SUCCESS.REQUIRE_ONE)
        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [False])
Пример #11
0
 def testStructure(self):
     tree = owyl.sequence(owyl.succeed(),
                          owyl.fail())
     viztree = OwylTree(tree)
     structure = truncate(viztree.get_structure(), ['name', 'children'])
     self.assertEquals(structure,
                       {'name': 'sequence',
                        'children': [{'name': 'succeed', 'children': []},
                                     {'name': 'fail', 'children': []}]})
Пример #12
0
    def testFail(self):
        """Can we fail?
        """
        s = owyl.fail()
        t = s()
        self.assertEqual(t.next(), False)
        self.assertRaises(StopIteration, t.next)

        t = s()
        self.assertEqual(t.next(), False)
        self.assertRaises(StopIteration, t.next)
Пример #13
0
    def testFail(self):
        """Can we fail?
        """
        s = owyl.fail()
        t = s()
        self.assertEqual(t.next(), False)
        self.assertRaises(StopIteration, t.next)

        t = s()
        self.assertEqual(t.next(), False)
        self.assertRaises(StopIteration, t.next)
Пример #14
0
    def testYieldHookSmallTree(self):
        tree = owyl.sequence(owyl.succeed(),
                             owyl.fail())
        viztree = OwylTree(tree)
        structure = viztree.get_structure()

        mock = Mock()
        viztree.on_yield += [mock]
        tree = viztree.tree_with_hooks
        [x for x in owyl.visit(tree)]

        mock.assert_has_calls([call(structure['children'][0]['id'], True),
                               call(structure['children'][1]['id'], False),
                               call(structure['id'], False)])
Пример #15
0
    def testVisitSequenceFailure(self):
        """Can we visit a failing sequence?
        """
        tree = owyl.sequence(owyl.succeed(), owyl.succeed(), owyl.fail(),
                             owyl.succeed())

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [True, True, False, False])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [True, True, False, False])
Пример #16
0
    def testParallel_DelayedSuccess(self):
        """Can parallel succeed if child succeeds later (one succeeds)?
        """
        # Succeed after 5 iterations.
        after = 5
        tree = owyl.parallel(owyl.fail(),
                             owyl.succeedAfter(after=after),
                             policy=owyl.PARALLEL_SUCCESS.REQUIRE_ONE)
        v = owyl.visit(tree)
        results = [x for x in v if x is not None]
        self.assertEqual(results, [True])

        v = owyl.visit(tree)
        results = [x for x in v if x is not None]
        self.assertEqual(results, [True])
Пример #17
0
    def testVisitSequenceFailure(self):
        """Can we visit a failing sequence?
        """
        tree = owyl.sequence(owyl.succeed(),
                             owyl.succeed(),
                             owyl.fail(),
                             owyl.succeed())

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [True, True, False, False])

        v = owyl.visit(tree)

        results = [x for x in v if x is not None]
        self.assertEqual(results, [True, True, False, False])
Пример #18
0
 def testStructureBig(self):
     tree = owyl.parallel(owyl.sequence(owyl.repeatAlways(blackboard.setBB()), owyl.log()),
                          owyl.selector(owyl.repeatUntilSucceed(blackboard.checkBB())),
                          owyl.repeatUntilFail(owyl.fail()))
     viztree = OwylTree(tree)
     structure = truncate(viztree.get_structure(), ['name', 'children'])
     self.assertEquals(structure,
                       {'name': 'parallel',
                        'children': [{'name': 'sequence',
                                      'children': [{'name': 'repeatAlways',
                                                    'children': [{'name': 'setBB',
                                                                  'children': []}]},
                                                   {'name': 'log',
                                                    'children': []}]},
                                     {'name': 'selector',
                                      'children': [{'name': 'repeatUntilSucceed',
                                                    'children': [{'name': 'checkBB',
                                                                  'children': []}]}]},
                                     {'name': 'repeatUntilFail',
                                      'children': [{'name': 'fail',
                                                    'children': []}]}]})
Пример #19
0
    def makeBasicZenoTree(self):
        ## Zeno's Body Paint subtree
        zenoBodyPaint = \
            owyl.selector(
                owyl.sequence(
                    self.isNotSameBrushStroke(),
                    self.isGreater(num1=self.animationOutputDur, num2=2),
                    self.setVariable(var=self.actionName, value="BrushStrokeGesture"),
                    owyl.selector(  # try the action sequence (subtree) or report failure
                        owyl.sequence(
                            owyl.visit(self.announceAndResetTree, blackboard=self.blackboard),
                            self.showAction(action=self.actionName, part=self.HEAD_NECK)  # Finally play the action's animation
                        ),
                        owyl.sequence(
                            self.say(utterance="I'm not feeling inspired today..."),
                            owyl.fail()
                        )
                    )
                ),
                owyl.sequence(
                    self.setVariable(var=self.actionName, value="Idle"),
                    owyl.selector(  # try the command sequence (subtree) or report failure
                        owyl.sequence(
                            owyl.visit(self.announceAndResetTree, blackboard=self.blackboard),
                            self.showAction(action=self.actionName, part=self.HEAD_NECK)  # Finally play the action's animation
                        ),
                        owyl.sequence(
                            self.say(utterance="Why can't I stand?"),
                            owyl.fail()
                        )
                    )
                )
            )

        ## body behavior subtree
        zenoBodySubtree = \
            owyl.limit(
                owyl.repeatAlways(
                    owyl.selector(  # Select response to command or natural behavior
                        owyl.sequence(  # If the last audio or blender input is a command, then select a response
                            self.isCommand(commandName=self.commandName),
                            self.setVariable(var=self.bodyOrFace, value=self.UPPER_BODY),
                            owyl.visit(self.selectBasicCommandSubtree, blackboard=self.blackboard)
                        ),
                        # It's not a command, so start checking for natural behaviors
                        owyl.sequence(
                            # self.isNoSalientTarget(),
                            # self.isNoFaceTarget(),
                            # self.isNoAudioInput(),
                            # self.isNoRosInput(),
                            # self.isNoEmotionInput(),
                            self.isIdle(),
                            # There's nothing to do, so let's paint!
                            owyl.visit(zenoBodyPaint, blackboard=self.blackboard)
                        ),
                        owyl.sequence(
                            # TODO: the other natural actions, once we have a saliency target, etc.
                        )
                    )
                ),
                limit_period=0.4  # Yield to the other behaviors after every 400 milliseconds of processing
            )

        # face & neck behavior subtree
        zenoFaceSubtree = \
            owyl.limit(
                owyl.repeatAlways(
                    owyl.selector(  # Select from one of several mutually exclusive face & neck behaviors
                        owyl.sequence(  # If the last audio or blender input is a command, then select a response
                            self.isCommand(commandName=self.commandName),
                            self.setVariable(var=self.bodyOrFace, value=self.HEAD_NECK),
                            owyl.visit(self.selectBasicCommandSubtree, blackboard=self.blackboard)
                        ),
                        owyl.sequence(
                            # self.isSalientTarget(),
                            # self.isNoFaceTarget(),
                            # self.isNoAudioInput(),
                            # self.isNoRosInput(),
                            # self.isNoEmotionInput(),
                            self.isIdle(),
                            owyl.visit(self.faceGaze, blackboard=self.blackboard)
                        ),
                        owyl.sequence(
                            self.isFaceTarget()
                        )
                    )
                ),
                limit_period=0.4  # Yield to the other behaviors after every 400 milliseconds of processing
            )

        # Zeno's root tree
        zenoTree = \
            owyl.parallel(  # At the highest level, run several parallel behaviors
                owyl.visit(zenoBodySubtree, blackboard=self.blackboard),
                owyl.visit(zenoFaceSubtree, blackboard=self.blackboard),
                owyl.limit(
                    owyl.repeatAlways(
                        owyl.sequence(
                            # Poll for input coming from blender, for example buttons to stop movement, etc.
                            # May move this logic out of the behavior tree...
                            # self.pollForBlenderInput(),

                            # Listen for audio input from people talking, etc.
                            # Again, this might not be the best place for this...
                            # self.listenForAudioInput()
                        )
                    ),
                    limit_period=0.4  # Yield to the other behaviors after every 400 milliseconds of processing
                ),
                policy=owyl.PARALLEL_SUCCESS.REQUIRE_ALL
            )
        return owyl.visit(zenoTree, blackboard=self.blackboard)
Пример #20
0
    def __init__(self, tree_name):
        self.schedule(self.update)
        # self.BehaviorNode = rospy.init_node("behavior_tree")
        rospy.Subscriber("itf_listen", String, self.audioInputCallback)
        rospy.Subscriber("speech_active", Bool, self.isSpeakingCallback)
        rospy.Subscriber("facedetect", targets, self.faceDetectCallback)
        rospy.Subscriber("nmpt_saliency_point", targets, self.saliencyCallback)
        self.zenodial_listen_pub = rospy.Publisher("zenodial_listen", String, queue_size=1)
        self.robot_movement_pub = rospy.Publisher("robot_movement", String, queue_size=1)
        self.commandKeywords = {
                'Stop': ['stop', 'halt', 'abort', 'kill', 'panic', 'off', 'freeze', 'shut down', 'turn off', 'help', 'help me', 'abhor', 'a w***e', 'a bore'],
                'Walk Forward': ['forward', 'ahead', 'straight', 'forwards'],
                'Walk Backward': ['back', 'backward', 'back up', 'backwards'],
                'Turn Left': ['turn left', 'turn lefts', 'turns left'],
                'Turn Right': ['turn right', 'turn rights', 'turns right']}

        ### Inputs
        self.saliencyTargetPos = [0.0, 0.0]         # position of the current saliency target
        self.saliencyTargetVel = 0.0                # average velocity of the current saliency target over the last second
        self.saliencyTargetAge = 0                  # time since the last significant change in the saliency target position
        self.faceTargetPos = [[0.0, 0.0]]           # position of the current face target
        self.faceTargetVel = 0.0                    # average velocity of the current face target over the last second
        self.faceTargetAge = 0                      # time since the last significant change in the face target position
        self.bodyTargetPos = [[0.0, 0.0]]           # position of the current body target
        self.bodyTargetVel = 0.0                    # average velocity of the current body target over the last second
        self.bodyTargetAge = 0                      # time since the last significant change in the body target position
        self.audioInput = ""                        # string output of speech-to-text algorithm, raw form
        self.audioInputAge = 0                      # time since the last significant parse of the audio input
        self.audioInputVol = 0                      # average volume or magnitude of the last audio input
        self.rosInput = ""                          # string representation of miscellaneous commands from other ros components, usually blender
        self.rosInputAge = 0                        # time since the last ros command
        self.emotionInput = ""                      # string output of the audio-emotion-analysis algorithm
        self.emotionInputAge = 0                    # time since the last significant chance in emotional state
        self.speechOutput = ""                      # string representation of the last speech output from the robot
        self.speechOutputAge = 0                    # time since the last speech output from the robot
        self.animationOutput = ""                   # string representation of the last animation output from the robot
        self.animationOutputAge = ""                # time since the last animation output from the robot
        self.animationOutputDur = 0                 # for zeno body paint
        self.randomInput = 0                        # a random percentile for random behaviors

        ### Globals
        self.blinkChance = 0.011    # @ 60 fps a 1.1% chance to start a blink each frame should give us a nice frequency
        self.highBodyVel = 1        # Not sure what would be considered a high velocity for the body - use 1 for now
        self.eyeFreedom = 0
        self.neckFreedom = 0
        self.HEAD_NECK = "headneck"
        self.UPPER_BODY = "ubody"
        self.LOWER_BODY = "lbody"

        ### Locals
        self.commandName = ""
        self.actionName = ""
        self.bodyOrFace = ""
        self.targetPos = [[0.0, 0.0]]
        self.glanceOrSaccadeTargetPos = [[0.0, 0.0]]
        self.firstGreeting = False
        self.speechActive = False
        self.idleSince = 0
        self.blackboard = blackboard.Blackboard()

        ### Subtrees
        ## Blink Subtree. A small example of a tree to run in parallel with the other subtrees.
        # Assumes randomInput is recalculated each frame
        self.blinkSubtree = \
            owyl.limit(
                owyl.repeatAlways(
                    owyl.selector(
                        owyl.sequence(
                            self.isSwitchingTarget(),
                            # blink 50% more often when switching targets
                            self.isLess(num1=self.randomInput, num2=self.blinkChance*1.5),
                            self.blink()
                        ),
                        owyl.sequence(
                            owyl.selector(
                                self.isGreater(num1=linalg.norm(self.bodyTargetVel), num2=1),
                                self.isSpeaking()
                            ),
                            self.isLess(num1=self.randomInput, num2=self.blinkChance*1.2),
                            self.blink()
                        ),
                        owyl.sequence(
                            self.isLess(num1=self.randomInput, num2=self.blinkChance),
                            self.blink()
                        )
                    )
                ),
                limit_period=0.4  # Yield to the other behaviors after every 400 milliseconds of processing
            )

        ## Announce the action we're about to take and then reset the robot to a default stance.
        # Though we announce an action, this tree doesn't execute the action.
        # Assumes actionName has been set
        self.announceAndResetTree = \
            owyl.sequence(  # announce the action and then reset
                owyl.selector(  # If we're not speaking, then speak
                    self.isSpeaking(),
                    self.sayStartAction(commandName=self.actionToPhrase(self.actionName))
                ),
                owyl.selector(  # If we're no in a default stance, reset (blend) to the default stance
                    self.isDefaultStance(),
                    self.resetToDefaultStance()
                )
            )

        ## Executes a basic command, such as to play an animation.
        # Assumes commandName has been set
        # Assumes bodyOrFace has been set
        # Will announce the command (if not already speaking)
        # before showing the associated animation
        self.executeBasicCommandSubtree = \
            owyl.sequence(
                self.isCommand(commandName=self.commandName),
                self.setVariable(var=self.actionName, value=self.commandName),
                owyl.selector(  # try the command sequence (subtree) or report failure
                    owyl.sequence(
                        owyl.visit(self.announceAndResetTree, blackboard=self.blackboard),
                        self.showCommand(commandName=self.commandName, part=self.bodyOrFace),  # Finally play the command's animation
                    ),
                    owyl.sequence(
                        self.say(utterance="I'm sorry, Dave, I'm afraid I can't do that..."),
                        owyl.fail()
                    )
                )
            )

        ## Select a basic command to execute, once we know that we've been given a command.
        # Assumes bodyOrFace has been set, to distinguish body actions from face actions
        self.selectBasicCommandSubtree = \
            owyl.selector(  # Select from one of several mutually exclusive behaviors
                owyl.sequence(  # If we should be idling, then try to play the Idle animation...
                    self.setVariable(var=self.commandName, value="Idle"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="StopSpeech"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(  # If we're commanded to and can walk to target location, then play the walk animation until we reach the target
                    self.setVariable(var=self.commandName, value="WalkForward"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="WalkBackward"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="TurnLeft"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="TurnRight"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="PointUp"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="PointDown"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="LookUp"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="LookDown"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="Wave"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(  # If we should show an emotion, then select the right one and show it.
                    self.setVariable(var=self.commandName, value="Smile"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="Frown"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="FrownMouth"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                ),
                owyl.sequence(
                    self.setVariable(var=self.commandName, value="OpenMouth"),
                    owyl.visit(self.executeBasicCommandSubtree, blackboard=self.blackboard)
                )
            )

        ## Tracks the target face or salient point
        # Assumes targetPos has been set to face, body, or salient position
        self.faceGaze = \
            owyl.sequence(
                # TODO: Get clarification from Hanson and others on the conditions for tracking
                # owyl.selector(
                #   self.isFaceNearestAudioSource(self.faceTargetPos), # Do we have the source of the audio?
                #   self.isFaceMostSalient(self.faceTargetAge, self.saliencyTargetAge), # Do we know the degree/magnitude of saliency?
                #   self.isFaceCentered(self.faceTargetPos), # Can we find the centroid of all the faces?
                #   self.isLess(self.randomInput, self.blinkChance*2.0) # Should we really switch tracking targets this often?
                # ),

                # self.faceTrack(pos=targetPos, eyeFree=eyeFreedom, neckFree=neckFreedom, rand=-1)  # -1 here indicating that we'll track this point until told to stop
            )

        ## Displays the surprised emotional expression under certain conditions
        # Assumes targetPos has been set to face, body, or salient position
        self.startle = \
            owyl.sequence(
                owyl.selector(
                    self.isGreater(num1=self.audioInputVol, num2=1),  # or whatever counts for a high volume
                    self.isGreater(num1=linalg.norm(self.faceTargetVel), num2=1),
                    self.isGreater(num1=linalg.norm(self.bodyTargetVel), num2=1),
                    self.isGreater(num1=linalg.norm(self.saliencyTargetVel), num2=1)
                ),
                self.showAction(action="OpenMouth", part=self.HEAD_NECK)
                # self.showAction(action="Surprised", part="face")
            )

        ## Random eye movements which are much faster and less pronounced than glances.
        # Assumes targetPos has been set to face or salient position
        # Assumes glanceOrSaccadeTargetPos has been set to face's body or salient point nearby
        # Assumes eyeFreedom and neckFreedom have been set to appropriate degrees of freedom
        self.saccade = \
            owyl.selector(
                owyl.sequence(
                    self.isGreater(num1=self.randomInput, num2=0.5),
                    self.faceTrack(pos=self.glanceOrSaccadeTargetPos, eyeFree=self.randomInput*0.25*self.eyeFreedom, neckFree=self.randomInput*0.10*self.neckFreedom, rand=self.randomInput)
                ),
                owyl.sequence(
                    self.faceTrack(pos=self.glanceOrSaccadeTargetPos, eyeFree=self.randomInput*0.75*self.eyeFreedom, neckFree=self.randomInput*0.30*self.neckFreedom, rand=self.randomInput)
                )
            )

        ## Random eye movements which signal recognition of targets.
        # Assumes targetPos has been set to face or salient position
        # Assumes glanceOrSaccadeTargetPos has been set to face's body or salient point nearby
        self.glance = \
            owyl.selector(
                owyl.sequence(
                    owyl.selector(
                        self.isLess(num1=self.faceTargetAge, num2=1),
                        self.isLess(num1=self.randomInput, num2=0.0025)
                    ),
                    self.faceTrack(pos=self.glanceOrSaccadeTargetPos, eyeFree=self.eyeFreedom, neckFree=self.neckFreedom, rand=self.randomInput*2.5)
                ),
                owyl.sequence(
                    owyl.selector(
                        self.isLess(num1=self.saliencyTargetAge, num2=1),
                        self.isLess(num1=self.randomInput, num2=0.0025)
                    ),
                    self.faceTrack(pos=self.glanceOrSaccadeTargetPos, eyeFree=self.eyeFreedom, neckFree=self.neckFreedom, rand=self.randomInput*2.5)
                )
            )

        ## After tracking at a new target face, ZoidStein will execute a scripted greeting.
        # Be careful not to play this more than once in the same encounter.
        self.greeting = \
            owyl.sequence(
                self.isVariable(var=self.firstGreeting, value=False),
                self.setVariable(var=self.firstGreeting, value=True),
                self.say(utterance="Hello!"),
                self.showAction(action="Wave", part=self.UPPER_BODY),
                self.showAction(action="Smile", part=self.HEAD_NECK)
            )

        ## When people are too close, move head back and up while playing the afraid expression animation.
        self.awkward = \
            owyl.sequence(
                self.showAction(action="LookUp", part=self.HEAD_NECK),
                # self.showAction(action="Afraid", part="face")
                self.showAction(action="Frown", part=self.HEAD_NECK)
            )

        ## When people are very close, move head forward and down while playing the innoscent expression animation.
        self.shy = \
            owyl.sequence(
                self.showAction(action="LookDown", part=self.HEAD_NECK),
                # self.showAction(action="Innocent", part=self.HEAD_NECK)
                self.showAction(action="Frown", part=self.HEAD_NECK)
            )

        ## In general, ZoidStein's expressions should mimic the emotional input of its targets.
        self.mimic = \
            owyl.selector(
                owyl.sequence(
                    self.isVariable(var=self.emotionInput, value="Happy"),
                    self.showAction(action="Happy", part=self.UPPER_BODY),
                    self.showAction(action="Happy", part=self.HEAD_NECK)
                )
                # TODO: Do we have to mimic all the emotionInput or just happy?
            )

        """
        Creating the tree
        """
        for case in switch(tree_name):
            if case("BasicZenoTree"):
                # self.robot = Zeno()
                self.makeBasicZenoTree()
                break
            if case("BasicZoidSteinTree"):
                self.robot = Zoidstein()
                self.makeBasicZoidSteinTree()
                break
            if case():
                rospy.loginfo("Unrecognized Tree Name!\n")