The goal was to build a game that kids would think would be fun and engaging. There were lots of ideas ranging from catapults to drawing machines. After weeks of trying to work the details a bombsquad type game had evolved and was selected to build out. The below describes some of the evolution of the bombsquad game.
OverviewLEGO Bombsquad is an interactive game consisting of three key challenges each leveraging a unique LEGO Sensor and a clever interaction with Alexa. If any of the following steps are done out of order the bomb will explode and the user will need to start over. The premise is you are a bystander that showed up at the scene and you have radio contact with Bombsquad team but there isn't enough time for them to show up. So via walkie-talkie (Alexa Voice interaction) someone walks you through the steps. The voice element helps bring an element of insight to the game that wouldn't be available otherwise (i.e. what next step to take). It also helps bring a different level of engagement as there is physical interaction as well as voice interaction.
Initially there were many complicated and random steps that the user was going to have to perform but after dealing the complexities of sensors and messaging between EV3 and Alexa skill the interactions were greatly simplified. The steps are as follows and also have included commentary on design approach:
- Remote Detonation Blocking (Ultrasonic Sensor)
A simple track with a small cart is created that rolls back and forth along it with the ultrasonic sensor placed at the end. At the beginning of each game session a random distance is determined and the user must roll the cart back and forth to achieve the correct distance from the UltraSonic sensor. Every few seconds Alexa will give the user feedback on whether it should be closer or further from the sensor. The sensor, while fairly accurate does oscillate a little on the measurements. As a result the code only sends events when it detects a significant change and has some leniency so it doesn't lose "remote detonation" blocking due to small oscillation in the reading.
- Cutting the proverbial wire (Color Sensor)
Once remote detonation is disabled the user must "cut" one of the three color wires represented by 2x6 LEGO plates. A random color is selected from Red, Yellow, and Green at the beginning of the session and the LEDs on the EV3 Brick give the user the clue on what color to cut. The user takes the laser cutter (Color Sensor) and points it at the colored plate and says "Activate Laser Cutter". Triggering the Color Sensor proved to troublesom; polling resulted in sending no color or the incorrect color at an incorrect time. Thus an event based approach was used to give it more controlled experience. Because the desire was for voice activation the comm-link approach discussed below was necessary to allow for when the skill dropped into the background. (i.e. you took too long to select the color of the wire and Alexa timed out. By pressing the wheel it would bring the skill back into the foreground)
- Disable the Fuse (InfraRed Sensor and InfraRed Remote)
The fuse is protected by an oscillating LEGO block that raises and lowers over the remote. The oscillation starts at the beginning of the game session and increases in speed as you progress in accomplishment as well as time. The bomb is diffused as soon as the user turns off the remote by pushing the large gray button. Even though the other steps have to be completed before the desire was still to have some mechanical movement in place to "protect" the fuse. Multiple attempts with slip gears and hydraulics made the setup process too complicated as there was no easy way to determine current state of a motor. The final design is based on a pump jack type mechanism that can be started and stopped at any point and can easily be manipulated without power. This allowed you to "Reset the Bomb" at the beginning of each session.
- Comm-Link (Touch Button)
Not necessarily a required component or even interaction but a convenient way to re-initiate the interaction with the Skill. During development discovered that if the user didn't have a voice interaction with a short period of time the skill would get backgrounded and any commands sent wouldn't register with the skill or would be under a new session if you launched the skill again. By creating the comm-link approach the user can push the button to get a status and some tips but this also brings the skill back into the foreground so commands such as "Activate Laser Cutter" are received correctly.
Software ApproachAs the user interacts with the LEGO contraption or with the Alexa Voice component it's critical to keep the two components in sync. Every time an event/interaction occurs on LEGO side an event is sent to Alexa skill and processed by Lambda. Code snippet is shown here for Laser Cutter interaction:
else if (name === 'Color') {
var colorSeen = payload.colorSeen;
speechOutput = `<voice name="Matthew">You cut the ${colorSeen} wire! </voice>`;
if (attributesManager.getSessionAttributes().remoteDetonationBlocked) {
if (String(attributesManager.getSessionAttributes().colorOfWire) == (colorSeen)) {
speechOutput += `<voice name="Matthew">Great Job! Now you need to deactivate the fuse by pushing the button on the remote. Careful with your hand! You have ${payload.timeLeft} seconds left</voice>`;
Util.putSessionAttribute(handlerInput, 'wireCut', true);
} else {
speechOutput += `<voice name="Matthew">This was the wrong wire!<audio src="soundbank://soundlibrary/explosions/explosions/explosions_01"/>` + RESTART_PHRASE + `</voice>`;
Util.putSessionAttribute(handlerInput, 'bombExploded', true);
}
} else {
speechOutput += `<voice name="Matthew">You didn't deactivate the tamper detect ion!<audio src="soundbank://soundlibrary/explosions/explosions/explosions_01"/>` + RESTART_PHRASE + `</voice>`;
Util.putSessionAttribute(handlerInput, 'bombExploded', true);
}
sendStateToEV3(handlerInput);
return handlerInput.responseBuilder
.speak(speechOutput, playBehavior)
.withShouldEndSession(false)
.getResponse();
Note that at the end the code sends all the state back to EV3 where the following code handles any state changes. The follow snippet shows different events received and sent to Alexa skill. Some of the physical interactions including the oscillating arm are managed via threads and needed to be started and stopped at appropriate times. Pieces of the thread management is outlined below in context of different events. Pay special attention to where the LEDs are set to the color of the wire selected by Alexa skill code.
def on_custom_mindstorms_gadget_control(self, directive):
"""
Handles the Custom.Mindstorms.Gadget control directive.
:param directive: the custom directive with the matching namespace and name
"""
try:
payload = json.loads(directive.payload.decode("utf-8"))
print("Control payload: {}".format(payload))
control_type = payload["type"]
control_command = payload["command"]
if control_type == "query" and control_command == "color":
time.sleep(6)
if (self.color.color_name in ["Green", "Red", "Yellow"]):
print(self.color.color_name)
self._send_event(EventName.COLOR, {'colorSeen': self.color.color_name})
else:
self._send_event(EventName.SPEECH, {'speechOut': 'Careful! You need to make sure the laser cutter is pointed directly at color of wire you want to cut when you activate the laser cutter'})
if control_type == "query" and control_command == "init":
initObject = {'colorSeen': self.color.color_name, 'proximity': self.ir.distance(), 'ultrasonic': self.distance.distance_centimeters}
print("Init Object: " + json.dumps(initObject))
self._send_event(EventName.INIT, initObject)
if control_type == "session":
if (self.session and self.session['bombExploded']):
print("Explosion was detected")
self._kill_distance_thread = True
self._kill_proximity_thread = True
self._kill_touch_thread = True
self._kill_timer_thread = True
self.session = payload["session"]
print("Session: {}".format(self.session))
if (payload["newSession"]):
self.leds.set_color("LEFT", self.session['colorOfWire'].upper(), 1)
self.leds.set_color("RIGHT", self.session['colorOfWire'].upper(), 1)
self._kill_distance_thread = True
self._kill_proximity_thread = True
self._kill_touch_thread = True
self._kill_timer_thread = True
#wait for threads to die and talking to finish
time.sleep(8)
self.timeStart = int(time.time())
self._kill_distance_thread = False
self._kill_touch_thread = False
self._kill_proximity_thread = False
self._kill_timer_thread = False
threading.Thread(target=self._touch_thread, daemon=True).start()
threading.Thread(target=self._proximity_thread, daemon=True).start()
threading.Thread(target=self._distance_thread, daemon=True).start()
threading.Thread(target=self._timer_thread, daemon=True).start()
except KeyError:
print("Missing expected parameters: {}".format(directive))
Finished ProductOPTIONAL and at your own Risk: To avoid burning through countless AA batteries buy the following and then you can hardwire the power to the EV3 brick:
Lenink AA Battery Eliminator Converter,Replace AA Battery (Not Include Adapter)
Be sure to set the voltage to 9V. This has worked great for me but of course is unsupported by the platform and is to be performed at your own risk.
Step 0: Complete Setup Guide and Training MissionsFollow the steps outlined on the getting started guide for LEGO Mindstorms Voice Challenge to get your EV3 and Alexa environment up and running. It is recommended to complete all four missions to familiarize yourself with the environment. Once you complete Mission 4 you can easily follow the remaining steps below:
Step 1: LEGO- Follow the lego-bombsquad.pdf instructions attached to this project (referencing LEGO-BombSquad.io for more details by installing Studio)
This kit was predominately built with EV3 31313 Set. However an additional Ultrasonic sensor and several other LEGO/Technic pieces (leveraged set 30365-1 for the satellite component). See build instructions for component list
- Connect all the sensors to ports 1-4 with the various cables provided with EV3 kit
- Connect the Small motor to Port B (Code specifies Port B and will not start with another port)
- Upload bombsquad.py to the mission-04 folder (or create your own) and copy and rename mission-01.ini (with your amazon credentials) to bombsquad.ini and place in the same location as bombsquad.py
- Following what you learned in Mission 3 and Mission 4 - Change the Invocation name to "LEGO Bombsquad"
- Take the skill that you did for Mission 3 and Mission 4 and update the lambda code with attached index.js, package.json, common.js, util.js and copy and paste the contents of the attached model.json into the JSON editor for the model. Be sure to Build the model.
- Deploy the code like you did in Mission 4
- You should now be able to launch the code on the EV3 the same way you ran Mission 4 but run bombsquad.py instead. This may take several minutes to launch... (seriously... sometimes it took 3-4 minutes)
- Say "Alexa, Launch LEGO Bombsquad" and follow the steps. Have fun! and disarm the bomb!
Future Enhancements
- Exploding component on the LEGO side
- More fun sound effects on LEGO and Alexa side
- Additional challenges to solve on both Alexa and LEGO side
- Visual Helpers for Echo devices with Screens
- Introduce levels of difficulty
Comments