Making a multimodal presentation

Part 4: Controlling time more precisely

So far, all actions have been run either sequentially or, as in Part 2, running perfectly in parallel.

For the final part, however, we want to start a sound (and show an image) after a fixed delay:

Part 4
Schema of Pepper performance - part 4

1. A finer control of the timing

Sometimes, you might need to trigger a specific sound or image at an inconvenient moment - for example, in the middle of Pepper’s speech or animation.

Now, one way of doing this would be to split up the text (as you’ve been doing so far); but in some cases, this will ruin the prosody of the sentence.

Instead, use a timer so that a callback is triggered after a delay:

////////////////////////
// Presentation logic //
////////////////////////

private fun runPresentation() {
   // ...

   // Part 4: "And become beautiful"

   Timer("Diamond", false).schedule(2_000) {
       setImage(R.drawable.scene9)
       playMedia(R.raw.magic)
   }
}

You can then combine this with the other tricks we saw earlier to make a more complete moment:

////////////////////////
// Presentation logic //
////////////////////////

private fun runPresentation() {
   // ...

   // Part 4: "And become beautiful"

   Timer("Diamond", false).schedule(2_000) {
       setImage(R.drawable.scene9)
       playMedia(R.raw.magic)
   }
   val sayBeautiful = makeSay("and become beautiful and precious! All this thanks to you")
   val animateYeah = makeAnimate(R.raw.yeah_b001)
   Future.waitAll(sayBeautiful.async().run(), animateYeah.async().run()).value
   setImage(R.drawable.scene10)
   makeSay("I can't wait for what we are gonna do !").run()
   Thread.sleep(1_000)
   clearImage()
}

2. The final result

Here is the final presentation logic:

////////////////////////
// Presentation logic //
////////////////////////

private fun runPresentation() {

   // Part 1: "Making me talk..."

   setImage(R.drawable.scene1)
   makeSay("Okay, so ... making me talk is a first step a bit like ...").run()
   Thread.sleep(200)
   makeSay("a rolling rock ...").run()
   setImage(R.drawable.scene2)

   // Part 2: "Let me show you..."

   Thread.sleep(800)
   setImage(R.drawable.scene3)
   val sayMore = makeSay("But there's much more to do. Let me show you ! ...")
   val animateEnthusiast = makeAnimate(R.raw.nicereaction_a002)
   val animFuture = animateEnthusiast.async().run()
   animFuture.thenConsume {
       setImage(R.drawable.scene4)
   }
   Future.waitAll(sayMore.async().run(),
           animFuture).value

   // Part 3: "I can make sound"

   playMedia(R.raw.stone_breaks)
   setImage(R.drawable.scene5)
   makeSay("Like me, a rock can make sound.").run()
   setImage(R.drawable.scene6)
   Thread.sleep(1_000)
   setImage(R.drawable.scene7)
   makeSay("and light.").run()
   Thread.sleep(1_000)
   setImage(R.drawable.scene8)

   // Part 4: "And become beautiful"

   Timer("Diamond", false).schedule(2_000) {
       setImage(R.drawable.scene9)
       playMedia(R.raw.magic)
   }
   val sayBeautiful = makeSay("and become beautiful and precious! All this thanks to you")
   val animateYeah = makeAnimate(R.raw.yeah_b001)
   Future.waitAll(sayBeautiful.async().run(), animateYeah.async().run()).value
   setImage(R.drawable.scene10)
   makeSay("I can't wait for what we are gonna do !").run()
   Thread.sleep(1_000)
   clearImage()
}