資料介紹
描述
介紹:
根據(jù)美國國立衛(wèi)生研究院的說法,“健忘可能是衰老的正常部分。” 最重要的是,老年人也經(jīng)常隨著年齡的增長而面臨身體衰退。這些問題會導(dǎo)致一些問題,從忘記物品在哪里,到在獲取藥品或手杖等基本物品時體力消耗。
到目前為止,機(jī)器人護(hù)理已經(jīng)作為寵物產(chǎn)品進(jìn)入老年人市場,以類似的硬件和成本,我們實際上可以構(gòu)建機(jī)器人來為老年人做更多的事情。在本文中,我們將討論如何使用Lego Mindstorm EV3機(jī)器人幫助老年人存儲和取物。
第 1 步:構(gòu)建 GRIPP3R
MindStorm EV3 的 GRIPP3R 似乎是處理此類任務(wù)的最理想機(jī)器人,因為我們可以構(gòu)建機(jī)器人并用它來抓取物體。使用樂高 MindStorm 套裝搭建機(jī)器人大約需要 2-3 小時,但實際上只需要說明書的前 68 頁,因為其他所有內(nèi)容都非常美觀。
機(jī)器人完全建成后,我們首先需要測試一些基礎(chǔ)知識以確保其正常運(yùn)行。我們可以在https://www.lego.com/en-us/themes/mindstorms/downloads下載 MindStorms Home并使用基本功能。我們的第一個測試是看看我們正在嘗試做的事情是否可能,下面是我們編寫的一個簡單的小程序,用來抓取東西,轉(zhuǎn)身走開。
運(yùn)行此程序時,您應(yīng)該看到下圖,計算機(jī)運(yùn)行程序需要接線,我們最終產(chǎn)品不需要接線。現(xiàn)在完成了,我們可以進(jìn)入下一步。
第 2 步:準(zhǔn)備好開發(fā)環(huán)境
Alexa gadget 編寫了有關(guān)如何將 Alexa 與 Mindstorm 連接的完整設(shè)置指南,我們將只強(qiáng)調(diào)這一步的主要部分,強(qiáng)烈建議您通過那里設(shè)置環(huán)境。
設(shè)置GRIPP3R 端
在這一步中,我們使用 Visual Studio Code 和 EV3DEV 環(huán)境設(shè)置樂高頭腦風(fēng)暴環(huán)境。具體要了解的東西很少。
如果磚面朝下,USB 端口和 sd 卡位于積木的左側(cè),如果面向您,則位于機(jī)器人的左側(cè)。這花了一點時間來弄清楚。
我們現(xiàn)在可以插入 SD 卡并啟動 EV3,我們可以從 ev3dev 菜單設(shè)置 WiFi 網(wǎng)絡(luò)。
這將允許我們將 Visual Studio Code 直接連接到 ev3,而不是使用 USB 線。連接后請記住我們稍后可能需要的 ip,確保您的計算機(jī)與 ev3 磚在同一網(wǎng)絡(luò)上。
在 Mac/PC 端設(shè)置
我們需要可以在下載的 Microsoft VS Code。 您可以打開alexa-gadgets-mindstorms
文件夾以安裝ev3dev-browser擴(kuò)展,如AlexaGadget的環(huán)境設(shè)置指南中所述
單擊顯示推薦后,它應(yīng)顯示在左側(cè),如下所示。
我們可以啟動一個名為grapp3r helper 的新工作區(qū),并有一些空文件,或者只是從源代碼下載我的代碼。現(xiàn)在我們將做GRIPP3R端,我們可以連接到wifi而不是做USB編程。單擊此處連接我的設(shè)備后,應(yīng)該會顯示 ev3dev,如果沒有,您可以通過“我沒有看到我的設(shè)備”手動輸入 ip
單擊瀏覽器上的下載按鈕以測試它是否有效。如果它正常工作,所有東西都應(yīng)該加載到 ev3 磚中,我們都準(zhǔn)備好進(jìn)行環(huán)境設(shè)置了。
由于我們將使用藍(lán)牙來控制設(shè)備,因此我們也在這里啟用藍(lán)牙。
第 3 步:準(zhǔn)備 Alexa 語音服務(wù)
這一步緊跟 alexagadget 的使命 1 ,我建議您仔細(xì)閱讀該指南,讓您的積木準(zhǔn)備好響應(yīng) Alexa 的呼叫。我們將通過總結(jié)。
我們首先需要亞馬遜開發(fā)者賬號。如果您還沒有開發(fā)者帳戶,請注冊一個。我們需要在Alexa Voice Service 中創(chuàng)建一個產(chǎn)品。
保持簡單,讓我們使用與來自 alexagadget 的 Mission 1 相同的產(chǎn)品來創(chuàng)建產(chǎn)品。
- 名稱:頭腦風(fēng)暴 EV3
- 產(chǎn)品編號:EV3_01
- 產(chǎn)品類型:Alexa小工具
- 產(chǎn)品類別:Animatronic 或 Figure
- 產(chǎn)品描述:隨心所欲
- 跳過上傳圖片
- 您是否打算將該產(chǎn)品進(jìn)行商業(yè)銷售?:否
- 這是兒童產(chǎn)品還是以其他方式針對 13 歲以下的兒童?:否
創(chuàng)建產(chǎn)品后,我們將擁有應(yīng)用程序 ID 和應(yīng)用程序密碼。
我們將使用 alexamission-01 作為測試平臺,為此我們只需用您自己的方式更改 id 和 secret,請確保不需要引號。
[GadgetSettings]
amazonId = YOUR_GADGET_AMAZON_ID
alexaGadgetSecret = YOUR_GADGET_SECRET
[GadgetCapabilities]
Alexa.Gadget.StateListener = 1.0 - wakeword
我們可以像上一步一樣上傳代碼,完整的代碼解釋位于任務(wù) 01本身。
為了執(zhí)行代碼,我們將做一些與alexa gadget不同的事情,執(zhí)行這些代碼需要一些時間,有時我們會等待掛起而不知道原因。我們可以通過 shell 終端本身手動完成。
之后,我們可以像任何其他 linux 一樣執(zhí)行我們的文件。
此時我們可以使用 GRIPP3R 本身激活 alexa 喚醒詞。
第 4 步:構(gòu)建 Alexa 應(yīng)用程序
這一步緊密總結(jié)了alexagadget的使命3和使命4 ,因為我們需要可以構(gòu)建alexa app的基本功能。
我們需要在 alexa 控制臺下創(chuàng)建一個新技能,為了保持一致,我們將其命名為 mindstorms,就像任務(wù)一樣。
我們將通過 node js 使用自定義和 Alexa 托管的后端,這只是為了在您執(zhí)行任務(wù)時保持一致性,并使編寫不同的程序更容易
我們可以從任務(wù) 4 上傳 JSON 文件并從那里構(gòu)建它。只是不要發(fā)射任何大炮,因為 GRIPP3R 電機(jī)無法處理。獲取 json 復(fù)制并粘貼后,單擊構(gòu)建模型繼續(xù)。
這給了我們足夠的能力來做以下事情,我們稍后會談到這些。
- 意圖名稱(MoveIntent、SetSpeedIntent、SetCommandIntent)
- 插槽名稱(方向、持續(xù)時間、速度、命令)
- 槽值(“前進(jìn)”、“后退”、“1”、“2”、“100”)
在這些構(gòu)建完成后,我們將把任務(wù) 4 的所有文件上傳到 Alexa 代碼屏幕中的 lambda 中。詳細(xì)代碼說明可以看這里。
之后,我們可以進(jìn)入測試模式,為“開發(fā)”啟用技能測試
至于代碼,您可以上傳代碼庫,也可以按照任務(wù) 4 中的代碼立即進(jìn)行測試。
#!/usr/bin/env python3
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# You may not use this file except in compliance with the terms and conditions
# set forth in the accompanying LICENSE.TXT file.
#
# THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY DISCLAIMS, WITH
# RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
# THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
import os
import sys
import time
import logging
import json
import random
import threading
from enum import Enum
from agt import AlexaGadget
from ev3dev2.led import Leds
from ev3dev2.sound import Sound
from ev3dev2.motor import OUTPUT_A, OUTPUT_B, OUTPUT_C, MoveTank, SpeedPercent, MediumMotor
from ev3dev2.sensor.lego import InfraredSensor
# Set the logging level to INFO to see messages from AlexaGadget
logging.basicConfig(level=logging.INFO, stream=sys.stdout, format='%(message)s')
logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
logger = logging.getLogger(__name__)
class Direction(Enum):
"""
The list of directional commands and their variations.
These variations correspond to the skill slot values.
"""
FORWARD = ['forward', 'forwards', 'go forward']
BACKWARD = ['back', 'backward', 'backwards', 'go backward']
LEFT = ['left', 'go left']
RIGHT = ['right', 'go right']
STOP = ['stop', 'brake', 'halt']
class Command(Enum):
"""
The list of preset commands and their invocation variation.
These variations correspond to the skill slot values.
"""
MOVE_CIRCLE = ['circle', 'move around']
MOVE_SQUARE = ['square']
SENTRY = ['guard', 'guard mode', 'sentry', 'sentry mode']
PATROL = ['patrol', 'patrol mode']
FIRE_ONE = ['cannon', '1 shot', 'one shot']
FIRE_ALL = ['all shots', 'all shot']
class EventName(Enum):
"""
The list of custom event name sent from this gadget
"""
SENTRY = "Sentry"
PROXIMITY = "Proximity"
SPEECH = "Speech"
class MindstormsGadget(AlexaGadget):
"""
A Mindstorms gadget that can perform bi-directional interaction with an Alexa skill.
"""
def __init__(self):
"""
Performs Alexa Gadget initialization routines and ev3dev resource allocation.
"""
super().__init__()
# Robot state
self.sentry_mode = False
self.patrol_mode = False
# Connect two large motors on output ports B and C
self.drive = MoveTank(OUTPUT_B, OUTPUT_C)
self.weapon = MediumMotor(OUTPUT_A)
self.sound = Sound()
self.leds = Leds()
self.ir = InfraredSensor()
# Start threads
threading.Thread(target=self._patrol_thread, daemon=True).start()
threading.Thread(target=self._proximity_thread, daemon=True).start()
def on_connected(self, device_addr):
"""
Gadget connected to the paired Echo device.
:param device_addr: the address of the device we connected to
"""
self.leds.set_color("LEFT", "GREEN")
self.leds.set_color("RIGHT", "GREEN")
logger.info("{} connected to Echo device".format(self.friendly_name))
def on_disconnected(self, device_addr):
"""
Gadget disconnected from the paired Echo device.
:param device_addr: the address of the device we disconnected from
"""
self.leds.set_color("LEFT", "BLACK")
self.leds.set_color("RIGHT", "BLACK")
logger.info("{} disconnected from Echo device".format(self.friendly_name))
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), file=sys.stderr)
control_type = payload["type"]
if control_type == "move":
# Expected params: [direction, duration, speed]
self._move(payload["direction"], int(payload["duration"]), int(payload["speed"]))
if control_type == "command":
# Expected params: [command]
self._activate(payload["command"])
except KeyError:
print("Missing expected parameters: {}".format(directive), file=sys.stderr)
def _move(self, direction, duration: int, speed: int, is_blocking=False):
"""
Handles move commands from the directive.
Right and left movement can under or over turn depending on the surface type.
:param direction: the move direction
:param duration: the duration in seconds
:param speed: the speed percentage as an integer
:param is_blocking: if set, motor run until duration expired before accepting another command
"""
print("Move command: ({}, {}, {}, {})".format(direction, speed, duration, is_blocking), file=sys.stderr)
if direction in Direction.FORWARD.value:
self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(speed), duration, block=is_blocking)
if direction in Direction.BACKWARD.value:
self.drive.on_for_seconds(SpeedPercent(-speed), SpeedPercent(-speed), duration, block=is_blocking)
if direction in (Direction.RIGHT.value + Direction.LEFT.value):
self._turn(direction, speed)
self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(speed), duration, block=is_blocking)
if direction in Direction.STOP.value:
self.drive.off()
self.patrol_mode = False
def _activate(self, command, speed=50):
"""
Handles preset commands.
:param command: the preset command
:param speed: the speed if applicable
"""
print("Activate command: ({}, {})".format(command, speed), file=sys.stderr)
if command in Command.MOVE_CIRCLE.value:
self.drive.on_for_seconds(SpeedPercent(int(speed)), SpeedPercent(5), 12)
if command in Command.MOVE_SQUARE.value:
for i in range(4):
self._move("right", 2, speed, is_blocking=True)
if command in Command.PATROL.value:
# Set patrol mode to resume patrol thread processing
self.patrol_mode = True
if command in Command.SENTRY.value:
self.sentry_mode = True
self._send_event(EventName.SPEECH, {'speechOut': "Sentry mode activated"})
# Perform Shuffle posture
self.drive.on_for_seconds(SpeedPercent(80), SpeedPercent(-80), 0.2)
time.sleep(0.3)
self.drive.on_for_seconds(SpeedPercent(-40), SpeedPercent(40), 0.2)
self.leds.set_color("LEFT", "YELLOW", 1)
self.leds.set_color("RIGHT", "YELLOW", 1)
if command in Command.FIRE_ONE.value:
print("Fire one", file=sys.stderr)
self.weapon.on_for_rotations(SpeedPercent(100), 3)
self._send_event(EventName.SENTRY, {'fire': 1})
self.sentry_mode = False
print("Sent sentry event - 1 shot, alarm reset", file=sys.stderr)
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
if command in Command.FIRE_ALL.value:
print("Fire all", file=sys.stderr)
self.weapon.on_for_rotations(SpeedPercent(100), 10)
self._send_event(EventName.SENTRY, {'fire': 3})
self.sentry_mode = False
print("sent sentry event - 3 shots, alarm reset", file=sys.stderr)
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
def _turn(self, direction, speed):
"""
Turns based on the specified direction and speed.
Calibrated for hard smooth surface.
:param direction: the turn direction
:param speed: the turn speed
"""
if direction in Direction.LEFT.value:
self.drive.on_for_seconds(SpeedPercent(0), SpeedPercent(speed), 2)
if direction in Direction.RIGHT.value:
self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(0), 2)
def _send_event(self, name: EventName, payload):
"""
Sends a custom event to trigger a sentry action.
:param name: the name of the custom event
:param payload: the sentry JSON payload
"""
self.send_custom_event('Custom.Mindstorms.Gadget', name.value, payload)
def _proximity_thread(self):
"""
Monitors the distance between the robot and an obstacle when sentry mode is activated.
If the minimum distance is breached, send a custom event to trigger action on
the Alexa skill.
"""
count = 0
while True:
while self.sentry_mode:
distance = self.ir.proximity
print("Proximity: {}".format(distance), file=sys.stderr)
count = count + 1 if distance < 10 else 0
if count > 3:
print("Proximity breached. Sending event to skill", file=sys.stderr)
self.leds.set_color("LEFT", "RED", 1)
self.leds.set_color("RIGHT", "RED", 1)
self._send_event(EventName.PROXIMITY, {'distance': distance})
self.sentry_mode = False
time.sleep(0.2)
time.sleep(1)
def _patrol_thread(self):
"""
Performs random movement when patrol mode is activated.
"""
while True:
while self.patrol_mode:
print("Patrol mode activated randomly picks a path", file=sys.stderr)
direction = random.choice(list(Direction))
duration = random.randint(1, 5)
speed = random.randint(1, 4) * 25
while direction == Direction.STOP:
direction = random.choice(list(Direction))
# direction: all except stop, duration: 1-5s, speed: 25, 50, 75, 100
self._move(direction.value[0], duration, speed)
time.sleep(duration)
time.sleep(1)
if __name__ == '__main__':
gadget = MindstormsGadget()
# Set LCD font and turn off blinking LEDs
os.system('setfont Lat7-Terminus12x6')
gadget.leds.set_color("LEFT", "BLACK")
gadget.leds.set_color("RIGHT", "BLACK")
# Startup sequence
gadget.sound.play_song((('C4', 'e'), ('D4', 'e'), ('E5', 'q')))
gadget.leds.set_color("LEFT", "GREEN")
gadget.leds.set_color("RIGHT", "GREEN")
# Gadget main entry point
gadget.main()
# Shutdown sequence
gadget.sound.play_song((('E5', 'e'), ('C4', 'e')))
gadget.leds.set_color("LEFT", "BLACK")
gadget.leds.set_color("RIGHT", "BLACK")
和ini文件
[GadgetSettings]
amazonId = amazonid
alexaGadgetSecret = secret
[GadgetCapabilities]
Custom.Mindstorms.Gadget = 1.0
這應(yīng)該使我們能夠控制機(jī)器人。我們將通過與下面相同的 shell 運(yùn)行。完成后,您應(yīng)該能夠控制機(jī)器人。
第 5 步:設(shè)置 Gripper Bot Alexa 端
現(xiàn)在是時候編寫機(jī)器人邏輯了。為了完成這個項目,我們需要機(jī)器人做 3 件事,來,拿東西,拿東西,按照從最簡單到最難的順序。這轉(zhuǎn)化為 ComeIntent、TakeIntent、BringIntent
在這一步中,我們將更改整個項目,因此以前的任務(wù)現(xiàn)在不是很有用。我們可以使用下面的json文件。其中一個重要的變化是“invocationName”:“gripper bot” ,所以我們可以調(diào)用gripper bot來幫助我們在Alexa中
{
"interactionModel": {
"languageModel": {
"invocationName": "gripper bot",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "HelloWorldIntent",
"slots": [],
"samples": [
"hello",
"how are you",
"say hi world",
"say hi",
"hi",
"say hello world",
"say hello"
]
},
{
"name": "ComeIntent",
"slots": [],
"samples": [
"Come",
"Come to me",
"Come here"
]
},
{
"name": "TakeIntent",
"slots": [
{
"name": "Item",
"type": "ItemType"
}
],
"samples": [
"Take this",
"Take it",
"Take this item",
"Take this {Item}",
"Take the {Item}"
]
},
{
"name": "BringIntent",
"slots": [
{
"name": "Item",
"type": "ItemType"
}
],
"samples": [
"Bring me the stuff",
"Bring me my item",
"Fetch my stuff",
"Bring me my {Item}"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
}
],
"types": [
{
"name": "ItemType",
"values": [
{
"name": {
"value": "bottle"
}
},
{
"name": {
"value": "cane"
}
},
{
"name": {
"value": "medicine"
}
},
{
"name": {
"value": "cup"
}
}
]
}
]
}
}
}
至于lamdba 中的index.js ,我們基于任務(wù) 4 添加了額外的 3 個 Intent,這很重要,因為我們將這些意圖傳遞給了抓取機(jī)器人本身。
// Construct and send a custom directive to the connected gadget with data from
// the ComeIntent.
const ComeIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'ComeIntent';
},
handle: function (handlerInput) {
const attributesManager = handlerInput.attributesManager;
let endpointId = attributesManager.getSessionAttributes().endpointId || [];
let speed = "50";
// Construct the directive with the payload containing the move parameters
let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
{
type: 'come',
command: 'come',
speed: speed
});
let speechOutput = 'Gripper Bot is coming to you';
return handlerInput.responseBuilder
.speak(speechOutput + BG_MUSIC)
.addDirective(directive)
.getResponse();
}
};
// Construct and send a custom directive to the connected gadget with data from
// the BringIntent.
const BringIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'BringIntent';
},
handle: function (handlerInput) {
let command = Alexa.getSlotValue(handlerInput.requestEnvelope, 'Item');
if (command === "" || command === null)
command = "it to you";
else{
command = command + " to you"
}
const attributesManager = handlerInput.attributesManager;
let endpointId = attributesManager.getSessionAttributes().endpointId || [];
let speed = attributesManager.getSessionAttributes().speed || "50";
// Construct the directive with the payload containing the move parameters
let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
{
type: 'bring',
command: command,
speed: speed
});
let speechOutput = 'bringing ' + command;
return handlerInput.responseBuilder
.speak(speechOutput + BG_MUSIC)
.addDirective(directive)
.getResponse();
}
};
// Construct and send a custom directive to the connected gadget with data from
// the BringIntent.
const TakeIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'TakeIntent';
},
handle: function (handlerInput) {
let command = Alexa.getSlotValue(handlerInput.requestEnvelope, 'Item');
if (command === "" || command === null)
command = "the item";
const attributesManager = handlerInput.attributesManager;
let endpointId = attributesManager.getSessionAttributes().endpointId || [];
let speed = attributesManager.getSessionAttributes().speed || "50";
// Construct the directive with the payload containing the move parameters
let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
{
type: 'take',
command: command,
speed: speed
});
let speechOutput = 'taking ' + command;
return handlerInput.responseBuilder
.speak(speechOutput + BG_MUSIC)
.addDirective(directive)
.getResponse();
}
};
// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
ComeIntentHandler,
TakeIntentHandler,
BringIntentHandler,
EventsReceivedRequestHandler,
ExpiredRequestHandler,
Common.HelpIntentHandler,
Common.CancelAndStopIntentHandler,
Common.SessionEndedRequestHandler,
Common.IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.addRequestInterceptors(Common.RequestInterceptor)
.addErrorHandlers(
Common.ErrorHandler,
)
.lambda();
完整代碼可以在代碼上傳端看到
第 6 步:編寫 GRIPP3R 輔助機(jī)器人邏輯
我們需要套件不附帶的陀螺儀傳感器(如果您有它,它包含在核心教育套件中)。我們可以在沒有它的情況下做到這一點,但是沒有它來計時 180 度轉(zhuǎn)彎是相當(dāng)不準(zhǔn)確的。
from ev3dev2.sensor.lego import GyroSensor
self.gyro = GyroSensor()
這里有 4 個主要的代碼審查,首先來。下面的代碼很簡單。
當(dāng) ComeIntent 讓 Robot 來找我們時,它會啟動 _come 向前移動。并且當(dāng)紅外傳感器檢測到任何低于55的東西時,它會停止,當(dāng)機(jī)器人停止時,它會打開把手,等待物品。
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), file=sys.stderr)
control_type = payload["type"]
if control_type == "move":
# Expected params: [direction, duration, speed]
self._move(payload["direction"], int(payload["duration"]), int(payload["speed"]))
elif control_type == "come":
self._come()
elif control_type == "take":
self._take()
elif control_type == "bring":
self._bring()
except KeyError:
print("Missing expected parameters: {}".format(directive), file=sys.stderr)
def _come(self, duration=10, speed=50):
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
self.isComing = True
self._move(Direction.FORWARD.value[0], duration, speed)
def _proximity_thread(self):
"""
Monitors the distance between the robot and an obstacle when sentry mode is activated.
If the minimum distance is breached, send a custom event to trigger action on
the Alexa skill.
"""
if distance <= 55:
"""
When the bot is coming, it will stop and open up it's arm
"""
if self.isComing == True:
self.isComing = False
print("Proximity breached, stopping")
self._move(Direction.STOP.value[0], 0, 0,)
self.leds.set_color("LEFT", "RED", 1)
self.leds.set_color("RIGHT", "RED", 1)
while not self.touch.is_pressed:
self.grip.on_for_degrees(SpeedPercent(10), -90)
print("Lowered the grip")
對于接下來的 2 個部分,我們需要轉(zhuǎn)動,在紅外距離傳感器的同一線程下,我們還將檢測轉(zhuǎn)動,我們將電機(jī)移動得非常慢,以便我們可以檢測到準(zhǔn)確的角度,每當(dāng)它達(dá)到 180 度時,機(jī)器人就會停止,繼續(xù)執(zhí)行下一個狀態(tài)。
self.gyro.reset()
self.isTurning = True
self.gyro.mode = 'GYRO-RATE'
self.gyro.mode = 'GYRO-ANG'
self.drive.on_for_seconds(SpeedPercent(4), SpeedPercent(-4), 40, block=False)
if self.isTurning == True:
print("angle: {}".format(angle), file=sys.stderr)
self.leds.set_color("LEFT", "YELLOW", 1)
self.leds.set_color("RIGHT", "YELLOW", 1)
if abs(angle) >= 179 or abs(angle) <= -181:
self.isTurning = False
self._move(Direction.STOP.value[0], 0, 0,)
self.gyro.reset()
self.gyro.mode = 'GYRO-RATE'
self.gyro.mode = 'GYRO-ANG'
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
當(dāng) TakeIntent 從服務(wù)器被命中時,我們將命中 _take 函數(shù)。它將抓住物品,轉(zhuǎn)動 180 度,然后前往基地。當(dāng)紅外傳感器擊中時,它會掉落物品,后退一秒鐘并轉(zhuǎn)回 180 度。
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), file=sys.stderr)
control_type = payload["type"]
if control_type == "move":
# Expected params: [direction, duration, speed]
self._move(payload["direction"], int(payload["duration"]), int(payload["speed"]))
elif control_type == "come":
self._come()
elif control_type == "take":
self._take()
def _take(self, duration=10, speed=50):
self.grip.on_for_rotations(SpeedPercent(100), 1)
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
self.gyro.reset()
self.gyro.mode = 'GYRO-RATE'
self.gyro.mode = 'GYRO-ANG'
self.isTurning = True
self.drive.on_for_seconds(SpeedPercent(4), SpeedPercent(-4), 40)
self.isTaking = True
self.drive.on_for_seconds(SpeedPercent(50), SpeedPercent(50), duration)
elif self.isTaking ==True:
self.isTaking = False
print("Proximity breached, stopping")
self._move(Direction.STOP.value[0], 0, 0,)
self.leds.set_color("LEFT", "RED", 1)
self.leds.set_color("RIGHT", "RED", 1)
while not self.touch.is_pressed:
self.grip.on_for_degrees(SpeedPercent(10), -90)
print("Dropping Item")
self.drive.on_for_seconds(SpeedPercent(-50), SpeedPercent(-50), 1)
self.gyro.reset()
self.isTurning = True
self.gyro.mode = 'GYRO-RATE'
self.gyro.mode = 'GYRO-ANG'
self.drive.on_for_seconds(SpeedPercent(4), SpeedPercent(-4), 40, block=False)
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
BringIntent 是最復(fù)雜的一個。一旦將控制權(quán)傳遞給機(jī)器人,我們首先調(diào)用_bring函數(shù),它會轉(zhuǎn)180度,步行1秒并抓住物品,然后它會轉(zhuǎn)180度,來到我們身邊,一旦通過紅外傳感器檢測到我們,它就會下降物品和走回來的時間與它走到我們身邊的時間相同。
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), file=sys.stderr)
control_type = payload["type"]
if control_type == "move":
# Expected params: [direction, duration, speed]
self._move(payload["direction"], int(payload["duration"]), int(payload["speed"]))
elif control_type == "come":
self._come()
elif control_type == "take":
self._take()
elif control_type == "bring":
self._bring()
def _bring(self, duration=10):
self.isTurning = True
self.gyro.mode = 'GYRO-RATE'
self.gyro.mode = 'GYRO-ANG'
self.drive.on_for_seconds(SpeedPercent(4), SpeedPercent(-4), 40)
self.drive.on_for_seconds(SpeedPercent(50), SpeedPercent(50), 1)
self.grip.on_for_rotations(SpeedPercent(100), 1)
self.isTurning = True
self.gyro.mode = 'GYRO-RATE'
self.gyro.mode = 'GYRO-ANG'
self.drive.on_for_seconds(SpeedPercent(4), SpeedPercent(-4), 40)
self.isBringing = True
self.now = time.time()
self.drive.on_for_seconds(SpeedPercent(50), SpeedPercent(50), duration)
self.leds.set_color("LEFT", "GREEN", 1)
self.leds.set_color("RIGHT", "GREEN", 1)
def _proximity_thread(self):
if distance <= 55:
elif self.isBringing ==True:
self.isBringing = False
print("Proximity breached, stopping")
self._move(Direction.STOP.value[0], 0, 0)
self.later = time.time()
self.leds.set_color("LEFT", "RED", 1)
self.leds.set_color("RIGHT", "RED", 1)
while not self.touch.is_pressed:
self.grip.on_for_degrees(SpeedPercent(10), -90)
print("Dropping Item")
difference = int(self.later - self.now)
self.drive.on_for_seconds(SpeedPercent(-50), SpeedPercent(-50), difference)\
第 7 步:演示!
通過這 3 個功能,我們基本上可以讓機(jī)器人為我們存儲物品,并在我們需要時獲取物品。該機(jī)器人能夠存儲從藥瓶到奶瓶的任何東西。這些功能對行動不便的老年人特別有幫助。
我們在 300 美元以下構(gòu)建了所有這些,您絕對可以按照指南在 20 小時內(nèi)完成。這是一個開源項目,我們可以改進(jìn)這些功能并在未來幫助老年人。
- 檢測機(jī)器人開源分享
- 基于Jetson NANO的助手機(jī)器人
- 坦克機(jī)器人開源分享
- 掃地機(jī)器人開源資料 43次下載
- 機(jī)器人守衛(wèi)開源分享
- 伺服機(jī)器人開源分享
- 基于Python的AI助手機(jī)器人 1次下載
- 英雄機(jī)器人開源
- 機(jī)器人開源案例
- 3R平面藝術(shù)機(jī)器人開源分享
- Arduino機(jī)器人開源分享
- 帶有Arduino和Python的AI助手機(jī)器人
- 基于DSP和PC的農(nóng)業(yè)機(jī)器人控制系統(tǒng) 17次下載
- 基于EtherCAT和TwinCAT3的協(xié)作機(jī)器人控制系統(tǒng) 14次下載
- 開架式通用水下機(jī)器人開源搭建手冊.pdf 11次下載
- 字節(jié)發(fā)布機(jī)器人領(lǐng)域首個開源視覺-語言操作大模型,激發(fā)開源VLMs更大潛能 360次閱讀
- 機(jī)器人技術(shù)中常用的路徑規(guī)劃算法的開源庫 843次閱讀
- 面對疫情 醫(yī)療機(jī)器人能幫上什么忙? 2126次閱讀
- dfrobotSparki機(jī)器人套裝簡介 2064次閱讀
- 醫(yī)用機(jī)器人的定義_醫(yī)用機(jī)器人發(fā)展 3122次閱讀
- 醫(yī)用機(jī)器人的功能_醫(yī)用機(jī)器人分類 2227次閱讀
- 協(xié)作機(jī)器人的起源_為什么需要協(xié)作機(jī)器人 8127次閱讀
- 盤點2018年機(jī)器人領(lǐng)域十大技術(shù) 3312次閱讀
- 如何區(qū)分機(jī)器人、協(xié)作機(jī)器人和移動機(jī)器人? 6828次閱讀
- 關(guān)于機(jī)器人傳感器的種類介紹 1.3w次閱讀
- 軟體機(jī)器人 前所未見的機(jī)器人 3692次閱讀
- 機(jī)器人的最佳編程語言是什么?機(jī)器人十大流行編程語言匯總 3.4w次閱讀
- 何為柔性機(jī)器人?如何讓機(jī)器人的身體柔若無骨? 1.1w次閱讀
- 手機(jī)如何連接小米掃地機(jī)器人_小米掃地機(jī)器人怎么連wifi 17.6w次閱讀
- 3種奇葩機(jī)器人的簡單介紹 5321次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
- 1.06 MB | 532次下載 | 免費(fèi)
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費(fèi)
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費(fèi)
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費(fèi)
- 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
- 6.40 MB | 227次下載 | 免費(fèi)
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費(fèi)
- 7元宇宙底層硬件系列報告
- 13.42 MB | 182次下載 | 免費(fèi)
- 8FP5207XR-G1中文應(yīng)用手冊
- 1.09 MB | 178次下載 | 免費(fèi)
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費(fèi)
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費(fèi)
- 4開關(guān)電源設(shè)計實例指南
- 未知 | 21549次下載 | 免費(fèi)
- 5電氣工程師手冊免費(fèi)下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費(fèi)
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費(fèi)
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費(fèi)
- 8《LED驅(qū)動電路設(shè)計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費(fèi)
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費(fèi)
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費(fèi)
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費(fèi)
- 6電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191187次下載 | 免費(fèi)
- 7十天學(xué)會AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183279次下載 | 免費(fèi)
- 8proe5.0野火版下載(中文版免費(fèi)下載)
- 未知 | 138040次下載 | 免費(fèi)
評論
查看更多