Esempio n. 1
0
class IceBreaker(WOC):
    theFace = None
    
    def __init__(self):
        self._isCompleted = False
        self._face = None
        self._newRound = True
        self._questions = Questions()

    async def run(self, coz_conn: cozmo.conn.CozmoConnection):
        await Common.wochelper.initFaceHandlers(coz_conn,
                                                self.onFaceObserved,
                                                self.onFaceAppeared,
                                                self.onFaceDisappeared)
        self._robot = await coz_conn.wait_for_robot()
        self._initPose = self._robot.pose
        self._cube = None
        # start with the "next question button" cube placed in front of cozmo
        try:
            self._cube = await self._robot.world.wait_for_observed_light_cube(timeout=30)
            print("Found cube: %s" % self._cube)
        except asyncio.TimeoutError:
            print("Didn't find a cube")

        while True:
            if not self._face:
                # first spin fast, then spin slower to seek human face
                await self.crazySpin()
                await self.spin()
            else:
                # find a face, do interaction
                await self.moveCloser()
                await self.coreInteraction()
                await self.waitFinishInteraction()
                await self.afterInteraction()
            await asyncio.sleep(0.1)
        
    # spin to find any human face
    async def spin(self):
        # start spin
        if not self._robot.is_moving:
            # head up so that Cozmo can see faces
            spinAction = self._robot.set_head_angle(MAX_HEAD_ANGLE,
                                                 in_parallel=True)
            await self._robot.drive_wheels(-TURN_SPEED, TURN_SPEED)
            await spinAction.wait_for_completed()
            cozmo.logger.info("spinAction = %s", spinAction)

    # close up to human whose face is just seen by Cozmo
    async def moveCloser(self):
        # turn to human Cozmo saw
        await self._robot.turn_towards_face(self._face).wait_for_completed()
        # move closer
        action1 = self._robot.drive_straight(distance_mm(DISTANCE_HUMAN),
                                             speed_mmps(STRAIGHT_SPEED),
                                             should_play_anim=False,
                                             in_parallel=True)
        action2 = self._robot.set_lift_height(0.0,
                                              accel=1.0,
                                              in_parallel=True)
        await action1.wait_for_completed()
        cozmo.logger.info("action1 = %s", action1)
        await action2.wait_for_completed()
        cozmo.logger.info("action2 = %s", action2)
        
    # ask ice breaking question
    async def coreInteraction(self):
        self._question = self._questions.getRandomQuestion()
        (pitch, self._duration) = await self.customizeSpeech(self._question)
        print(self._question)
        print("pitch = %s, durationScalar = %s" % (pitch, self._duration))
        await self._robot.say_text(self._question,
                                   use_cozmo_voice=True,
                                   in_parallel=True,
                                   voice_pitch=pitch,
                                   duration_scalar=self._duration).wait_for_completed()

    # repeat question if repeating button is pressed
    async def repeatInteraction(self):
        pitch = random.uniform(MIN_PITCH, MAX_PITCH)
        await self._robot.say_text(self._question,
                                   use_cozmo_voice=True,
                                   in_parallel=True,
                                   voice_pitch=pitch,
                                   duration_scalar=self._duration).wait_for_completed()
    
    # use cubes to finish interaction with human
    async def waitFinishInteraction(self):
        finishConfirmed = False
        while not finishConfirmed:
            cube = None

            await self._robot.set_head_angle(degrees(0),
                                             in_parallel=True).wait_for_completed()
            await self._robot.play_anim_trigger(cozmo.anim.Triggers.MeetCozmoGetIn).wait_for_completed()
            
            # wait to see a cube
            try:
                cube = await self._robot.world.wait_for_observed_light_cube(timeout=30)
                print("Found cube: %s" % cube)
            except asyncio.TimeoutError:
                print("Didn't find a cube")
            finally:
                pass

            # found ANY cube
            if cube:
                # set cube flashing light
                cube.set_lights(CUBE_READY_LIGHT)
                # Cozmo being curious

                await self._robot.play_anim_trigger(cozmo.anim.Triggers.BlockReact).wait_for_completed()
                await asyncio.sleep(1)
                # finishConfirmed = True

                tapped = None

                # wait this cube to be tapped
                try:
                    tapped = await cube.wait_for_tap(timeout=30)
                    print("Cube tapped: %s" % tapped)
                except asyncio.TimeoutError:
                    print("Didn't tap the cube")

                if tapped:
                    # show the cube is tapped
                    cube.set_lights(cozmo.lights.green_light)
                    
                    # the tapped cube is the cube of "next question"
                    if cube == self._cube:
                        finishConfirmed = True
                        await self._robot.play_anim_trigger(cozmo.anim.Triggers.BuildPyramidSuccess).wait_for_completed()
                    # other cube
                    else:
                        await self.repeatInteraction()
                    cube.set_lights_off()
            else:
                # didn't find cube
                await self._robot.play_anim_trigger(cozmo.anim.Triggers.DriveStartAngry).wait_for_completed()
            
    # return to spin position to start next round
    async def afterInteraction(self):
        await self._robot.go_to_pose(self._initPose).wait_for_completed()
##        await self._robot.turn_in_place(TURN_ANGLE_AFTER_INTERACTION).wait_for_completed()
        self._newRound = True
##        await self._robot.drive_straight(distance_mm(-DISTANCE_HUMAN),
##                                         speed_mmps(STRAIGHT_SPEED),
##                                         should_play_anim=False).wait_for_completed()

    # customize speech voice pitch and length
    async def customizeSpeech(self, question):
        pitch = random.uniform(MIN_PITCH, MAX_PITCH)
        length = len(question) - question.count(' ')
        duration = log_mapping(10, MIN_DURATION, 100, MAX_DURATION, length, 10)
        return (pitch, duration)
        
    # fast spin, don't care about faces
    async def crazySpin(self):
        if self._newRound:
            t = random.uniform(MIN_CRAZY_SPIN_TIME, MAX_CRAZY_SPIN_TIME)
            await self._robot.drive_wheels(-TURN_SPEED_FAST, TURN_SPEED_FAST)
            await asyncio.sleep(t)
            self._robot.stop_all_motors()
            await asyncio.sleep(0.5)
            self._newRound = False
    
    async def onFaceObserved(self, evt: cozmo.faces.EvtFaceObserved, obj=None, **kwargs):
        if self._face and self._face == evt.face:
            pass

    async def onFaceAppeared(self, evt: cozmo.faces.EvtFaceAppeared, obj=None, **kwargs):
        if not self._face:
            self._face = evt.face
            self._robot.stop_all_motors()
            print("Find a face, start tracking")
        if not self.theFace:
            self.theFace = evt.face

    async def onFaceDisappeared(self, evt: cozmo.faces.EvtFaceDisappeared, obj=None, **kwargs):
        if self._face and self._face == evt.face:
            self._face = None
            print("Lose tracking face")
Esempio n. 2
0
class CozmoQuiz(WOC):

    cl = None
    exit_flag = False
    audioThread = None
    curEvent = None
    idleAnimations = [
        'anim_sparking_idle_03', 'anim_sparking_idle_02',
        'anim_sparking_idle_01'
    ]
    attractAttentionAnimations = [
        'anim_keepaway_pounce_02', 'reacttoblock_triestoreach_01'
    ]
    numMap = {
        'CustomObjectTypes.CustomType00': '0',
        'CustomObjectTypes.CustomType01': '1',
        'CustomObjectTypes.CustomType02': '2',
        'CustomObjectTypes.CustomType03': '3',
        'CustomObjectTypes.CustomType04': '4',
        'CustomObjectTypes.CustomType05': '5',
        'CustomObjectTypes.CustomType06': '6',
        'CustomObjectTypes.CustomType07': '7',
        'CustomObjectTypes.CustomType08': '8',
        'CustomObjectTypes.CustomType09': '9'
    }
    animCtr = 0
    face = None
    lookingForFace = False
    buzzerWinner = None
    timeToAnswer = 15
    currentPlayer = 0
    numPlayers = 2  #get input later from command line
    turnsCompleted = 0
    numList = []
    answerGiven = False
    questions = None
    currentQuestion = None
    questionAsked = False
    playerTries = []
    startPose = None
    totalQuestions = 4
    questionsAsked = []
    playerScores = []
    points = [10, 5]
    questionNum = 0

    def __init__(self, *a, **kw):

        sys.setrecursionlimit(0x100000)

        self.questions = Questions()

        cozmo.setup_basic_logging()
        #         cozmo.connect_with_tkviewer(self.startResponding)
        cozmo.connect(self.startResponding)

    def startResponding(self, coz_conn):
        asyncio.set_event_loop(coz_conn._loop)
        self.coz = coz_conn.wait_for_robot()

        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType00,
                                          CustomObjectMarkers.Circles2, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType01,
                                          CustomObjectMarkers.Diamonds2, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType02,
                                          CustomObjectMarkers.Hexagons2, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType03,
                                          CustomObjectMarkers.Circles3, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType04,
                                          CustomObjectMarkers.Diamonds3, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType05,
                                          CustomObjectMarkers.Hexagons3, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType06,
                                          CustomObjectMarkers.Circles4, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType07,
                                          CustomObjectMarkers.Diamonds4, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType08,
                                          CustomObjectMarkers.Hexagons4, 100,
                                          90, 90, False)
        self.coz.world.define_custom_cube(CustomObjectTypes.CustomType09,
                                          CustomObjectMarkers.Circles5, 100,
                                          90, 90, False)

        self.startPose = self.coz.pose
        look_around = self.coz.start_behavior(
            cozmo.behavior.BehaviorTypes.LookAroundInPlace)

        try:
            self.cubes = self.coz.world.wait_until_observe_num_objects(
                self.numPlayers,
                object_type=cozmo.objects.LightCube,
                timeout=60)
        except asyncio.TimeoutError:
            print("Didn't find a cube :-(")
            return
        finally:
            look_around.stop()
            for i in range(0, len(self.cubes)):
                self.cubes[i].set_lights(Colors.WHITE)
                self.playerScores.append(0)
            self.coz.go_to_pose(self.startPose).wait_for_completed()
            self.coz.say_text("Welcome to Math Buzz",
                              duration_scalar=1.5,
                              voice_pitch=-1,
                              in_parallel=False).wait_for_completed()
            self.coz.play_anim('anim_greeting_happy_01').wait_for_completed()
            self.coz.say_text("Let's start!!",
                              duration_scalar=1,
                              voice_pitch=-1,
                              in_parallel=False).wait_for_completed()
            self.askNextQuestion()

        while not self.exit_flag:
            asyncio.sleep(0)
        self.coz.abort_all_actions()

    def on_object_tapped(self, event, *, obj, tap_count, tap_duration,
                         tap_intensity, **kw):
        if self.questionAsked is True:
            if obj not in self.playerTries:
                self.playerTries.append(obj)
                for i in range(0, len(self.cubes)):
                    self.cubes[i].set_lights_off()
                    if obj == self.cubes[i]:
                        self.currentPlayer = i
                        self.coz.go_to_object(
                            obj,
                            cozmo.util.distance_mm(250),
                            in_parallel=False).wait_for_completed()
                        self.startTimerAndWaitForAnswer()
                        obj.set_lights(Colors.BLUE)

    def startTimerAndWaitForAnswer(self):

        #Set up event handlerss
        self.coz.world.add_event_handler(cozmo.objects.EvtObjectAppeared,
                                         self.foundMarker)
        self.coz.world.add_event_handler(cozmo.objects.EvtObjectDisappeared,
                                         self.removeMarker)

        Timer(self.timeToAnswer, self.checkAnswer).start()

    def checkAnswer(self):

        self.numList.sort(key=lambda c: c.pose.position.y)

        num = ""

        for i in range(0, len(self.numList)):
            num += self.numMap[str(self.numList[i].object_type)]

        print("The number is ")

        if num == '':
            num = '0'

        print(num)
        if int(num) == int(self.currentQuestion['answer']):
            self.playerScores[self.currentPlayer] += self.points[
                len(self.playerTries) - 1]
            self.coz.say_text("Right Answer! You win " +
                              str(self.points[len(self.playerTries) - 1]) +
                              " points",
                              duration_scalar=1.5,
                              voice_pitch=-1,
                              in_parallel=False).wait_for_completed()
            self.coz.play_anim(
                'anim_rtpkeepaway_playeryes_02').wait_for_completed()
            self.askNextQuestion()
        else:
            self.coz.play_anim(
                'anim_keepaway_losegame_01').wait_for_completed()
            self.playerScores[self.currentPlayer] -= 10
            print(self.playerScores)
            self.goToNextPlayer()

    def goToNextPlayer(self):

        self.numList = []

        self.coz.say_text("You are wrong.. You lose 10 points",
                          duration_scalar=1.5,
                          voice_pitch=-1,
                          in_parallel=False).wait_for_completed()
        self.turnsCompleted += 1

        if self.turnsCompleted < self.numPlayers - 1:

            for i in range(0, len(self.cubes)):
                self.cubes[i].set_lights_off()
                if i != self.currentPlayer and i not in self.playerTries:
                    self.cubes[i].set_lights(Colors.WHITE.flash())
                    self.buzzerWinner = None
        else:
            self.askNextQuestion()

    def askNextQuestion(self):

        self.questionNum += 1

        if self.questionNum < self.totalQuestions:
            self.coz.go_to_pose(self.startPose).wait_for_completed()
            allPlayerScores = ' '.join(
                str(score) for score in self.playerScores)
            if self.questionNum > 1:
                self.coz.say_text("End of Round " + str(self.questionNum - 1) +
                                  ". The scores are " + allPlayerScores,
                                  duration_scalar=1.75,
                                  voice_pitch=-1,
                                  in_parallel=False).wait_for_completed()
            self.coz.say_text("Round " + str(self.questionNum),
                              duration_scalar=1.75,
                              voice_pitch=-1,
                              in_parallel=False).wait_for_completed()
            self.playerTries = []
            self.currentPlayer = 0
            self.buzzerWinner = None
            self.questionAsked = False

            for i in range(0, len(self.cubes)):
                self.cubes[i].set_lights_off()

            self.coz.world.add_event_handler(cozmo.objects.EvtObjectTapped,
                                             self.on_object_tapped)
            self.turnsCompleted = 0
            self.currentPlayer = 0
            #go to next question

            while (True):
                self.currentQuestion = self.questions.getRandomQuestion()
                if self.currentQuestion in self.questionsAsked:
                    continue
                else:
                    self.questionsAsked.append(self.currentQuestion)
                    break

            self.coz.say_text("What is " + self.currentQuestion['question'],
                              duration_scalar=1.75,
                              voice_pitch=-1,
                              in_parallel=False).wait_for_completed()
            self.coz.say_text("GO",
                              duration_scalar=1,
                              voice_pitch=-1,
                              in_parallel=False).wait_for_completed()
            for i in range(0, len(self.cubes)):
                self.cubes[i].set_lights(Colors.WHITE.flash())
            self.questionAsked = True
        else:
            self.findWinner()

    def findWinner(self):
        for i in range(0, len(self.cubes)):
            self.cubes[i].set_lights_off()
        self.coz.go_to_pose(self.startPose).wait_for_completed()
        self.coz.say_text("Game over",
                          duration_scalar=1.75,
                          voice_pitch=-1,
                          in_parallel=False).wait_for_completed()
        index, value = max(enumerate(self.playerScores),
                           key=operator.itemgetter(1))
        print("The winner is " + str(index))
        self.cubes[index].set_lights(Colors.YELLOW.flash())
        self.coz.go_to_object(
            self.cubes[index],
            cozmo.util.distance_mm(150)).wait_for_completed()
        self.coz.play_anim(
            'anim_memorymatch_successhand_cozmo_04').wait_for_completed()
        self.coz.say_text("You win! Congratulations!!",
                          duration_scalar=1.75,
                          voice_pitch=-1,
                          in_parallel=False).wait_for_completed()

    def foundMarker(self, event, *, image_box, obj, pose, updated, **kw):
        if self.questionAsked == True:
            if 'Custom' in str(type(obj)):
                if obj not in self.numList:
                    self.numList.append(obj)
                    print(len(self.numList))

    def removeMarker(self, event, *, obj):
        if self.questionAsked == True:
            if obj in self.numList:
                self.numList.remove(obj)

    def playIdle(self):
        if self.lookingForFace == False:
            self.coz.play_anim(
                self.idleAnimations[self.animCtr]).wait_for_completed()
            self.playIdle()