์ด ํํ ๋ฆฌ์ผ์์๋ Node.js์ ์น ์์ฑ API๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ ์ ์ด ๊ธฐ๋ฅ์ด ์๋ ๋๋ก ์ฉ ํ๋ก๊ทธ๋จ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ํฌ๋ฆฌ์ฝฅํฐ - ์ต๋ฌด์ ARDrone 2.0.
์๋ฆผ: "Habr"์ ๋ชจ๋ ๋ ์๋ฅผ ์ํ - "Habr" ํ๋ก๋ชจ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ Skillbox ๊ณผ์ ์ ๋ฑ๋กํ ๋ 10 ๋ฃจ๋ธ ํ ์ธ.
Skillbox๋ ๋ค์์ ๊ถ์ฅํฉ๋๋ค. ์ค๊ธฐ ์ฝ์ค
"๋ชจ๋ฐ์ผ ๊ฐ๋ฐ์ PRO" .
์๊ฐ
๋๋ก ์ ๋๋์ต๋๋ค. ๋๋ ์ฟผ๋๋ฅผ ๊ฐ์ง๊ณ ๋๊ฑฐ๋, ์ฌ์ง๊ณผ ๋น๋์ค๋ฅผ ์ฐ๊ฑฐ๋, ๊ทธ๋ฅ ์ฆ๊ฑฐ์ด ์๊ฐ์ ๋ณด๋ด๋ ๊ฒ์ ์ ๋ง ์ข์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ฌด์ธ ํญ๊ณต๊ธฐ(UAV)๋ ๋จ์ํ ์ํฐํ ์ธ๋จผํธ ์ด์์ ์ฉ๋๋ก ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๋ค์ ์ํ๊ณ์์ ์ผํ๊ณ ๋นํ๋ฅผ ์ฐ๊ตฌํ๋ฉฐ ๊ตฐ๋์ ๋์ ๋ถ๋ฌธ ๋ํ์๋ค์ด ์ฌ์ฉํฉ๋๋ค.
์ด๋ฒ ํํ ๋ฆฌ์ผ์์๋ ๋๋ก ์ ์ ์ดํ ์ ์๋ ํ๋ก๊ทธ๋จ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์์ฑ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค. ์, ํฌ๋ฆฌ์ฝฅํฐ๋ ๊ทํ๊ฐ ์ง์ํ ๋๋ก ์ํํ ๊ฒ์ ๋๋ค. ๊ธฐ์ฌ ๋์๋ UAV ์ ์ด์ ๋ํ ๊ธฐ์ฑ ํ๋ก๊ทธ๋จ๊ณผ ๋น๋์ค๊ฐ ์์ต๋๋ค.
์ฒ
์ฐ๋ฆฌ์๊ฒ๋ ๋ค์์ด ํ์ํฉ๋๋ค:
- ์ต๋ฌด์ ARDrone 2.0;
- ์ด๋๋ท ์ผ์ด๋ธ;
- ์ข์ ๋ง์ดํฌ.
๊ฐ๋ฐ ๋ฐ ๊ด๋ฆฌ๋ Windows/Mac/Ubuntu๊ฐ ์ค์น๋ ์ํฌ์คํ ์ด์ ์์ ์ํ๋ฉ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ์ ๋ Mac๊ณผ Ubuntu 18.04๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ์ต๋๋ค.
์ํํธ์จ์ด
๋ค์์์ ์ต์ ๋ฒ์ ์ Node.js๋ฅผ ๋ค์ด๋ก๋ํ์ธ์.
๋ํ ํ์
ํฌ๋ฆฌ์ฝฅํฐ ์ดํดํ๊ธฐ
Parrot ARDrone์ ์๋ ๋ฐฉ์์ ์ดํดํด ๋ด ์๋ค. ์ด ํฌ๋ฆฌ์ฝฅํฐ์๋ XNUMX๊ฐ์ ๋ชจํฐ๊ฐ ์์ต๋๋ค.
๋ฐ๋์ชฝ ๋ชจํฐ๋ ๊ฐ์ ๋ฐฉํฅ์ผ๋ก ์๋ํฉ๋๋ค. ํ ์์ ์๊ณ ๋ฐฉํฅ์ผ๋ก, ๋ค๋ฅธ ์์ ์๊ณ ๋ฐ๋ ๋ฐฉํฅ์ผ๋ก ํ์ ํฉ๋๋ค. ๋๋ก ์ ์ง๊ตฌ ํ๋ฉด์ ๋ํ ๊ฒฝ์ฌ๊ฐ์ ๋ณ๊ฒฝํ๊ณ ๋ชจํฐ์ ํ์ ์๋์ ๊ธฐํ ์ฌ๋ฌ ๊ฐ์ง ์กฐ์ข
๊ฐ๋ฅํ ์์ง์์ ๋ณ๊ฒฝํ์ฌ ์์ง์
๋๋ค.
์ ๋ค์ด์ด๊ทธ๋จ์์ ๋ณผ ์ ์๋ฏ์ด ๋ค์ํ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณ๊ฒฝํ๋ฉด ํฌ๋ฆฌ์ฝฅํฐ์ ์ด๋ ๋ฐฉํฅ์ด ๋ณ๊ฒฝ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ผ์ชฝ ๋ฐ ์ค๋ฅธ์ชฝ ๋กํฐ์ ํ์ ์๋๋ฅผ ์ค์ด๊ฑฐ๋ ๋๋ฆฌ๋ฉด ๋กค์ด ์์ฑ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ๋๋ก ์ด ์๋ค๋ก ๋นํํ ์ ์์ต๋๋ค.
๋ชจํฐ์ ์๋์ ๋ฐฉํฅ์ ๋ณ๊ฒฝํ์ฌ ํฌ๋ฆฌ์ฝฅํฐ๊ฐ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ์์ง์ผ ์ ์๋๋ก ๊ธฐ์ธ๊ธฐ ๊ฐ๋๋ฅผ ์ค์ ํ์ต๋๋ค. ์ฌ์ค ํ์ฌ ํ๋ก์ ํธ์์๋ ๊ณต๊ธฐ์ญํ์ ๊ณต๋ถํ ํ์๊ฐ ์๊ณ ๊ธฐ๋ณธ ์๋ฆฌ๋ง ์ดํดํ๋ฉด ๋ฉ๋๋ค.
Parrot ARDrone์ ์๋ ๋ฐฉ์
๋๋ก ์ Wi-Fi ํซ์คํ์ ๋๋ค. ์ฝฅํฐ์ ๋ช ๋ น์ ์ฃผ๊ณ ๋ฐ์ผ๋ ค๋ฉด ์ด ์ง์ ์ ์ฐ๊ฒฐํด์ผ ํฉ๋๋ค. ์ฟผ๋์ฝฅํฐ๋ฅผ ์ ์ดํ ์ ์๋ ๋ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์ต๋๋ค. ๋ชจ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋๋ก ์ด ์ฐ๊ฒฐ๋์๋ง์ ํฐ๋ฏธ๋์ ์ด๊ณ Telnet 192.168.1.1 - ํฌ๋ฆฌ์ฝฅํฐ์ IP์
๋๋ค. Linux์ ๊ฒฝ์ฐ ๋ค์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ํคํ ์ฒ
์ฐ๋ฆฌ์ ์ฝ๋๋ ๋ค์ ๋ชจ๋๋ก ๋๋์ด์ง๋๋ค:
- ์์ฑ ๊ฐ์ง๋ฅผ ์ํ ์์ฑ API๊ฐ ํฌํจ๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค;
- ๋ช ๋ น์ ํํฐ๋งํ๊ณ ํ์ค๊ณผ ๋น๊ตํฉ๋๋ค.
- ๋๋ก ์ ๋ช ๋ น์ ๋ณด๋ด๋ ๊ฒ;
- ๋ผ์ด๋ธ ๋น๋์ค ๋ฐฉ์ก.
API๋ ์ธํฐ๋ท์ ์ฐ๊ฒฐ๋์ด ์๋ ํ ์๋ํฉ๋๋ค. ์ด๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ์ด๋๋ท ์ฐ๊ฒฐ์ ์ถ๊ฐํฉ๋๋ค.
์ด์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ฐจ๋ก์ ๋๋ค!
์ํธ
๋จผ์ ์ ํด๋๋ฅผ ๋ง๋ค๊ณ ํฐ๋ฏธ๋์ ์ฌ์ฉํ์ฌ ํด๋น ํด๋๋ก ์ ํํด ๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฐ ๋ค์ ์๋ ๋ช ๋ น์ ์ฌ์ฉํ์ฌ Node ํ๋ก์ ํธ๋ฅผ ๋ง๋ญ๋๋ค.
๋จผ์ ํ์ํ ์ข ์์ฑ์ ์ค์นํฉ๋๋ค.
npm ์ค์นโ
์ฐ๋ฆฌ๋ ๋ค์ ๋ช ๋ น์ ์ง์ํฉ๋๋ค:
- ์ด๋ฅํ๋ค;
- ์ฐฉ๋ฅ;
- ์๋ก-๋๋ก ์ด XNUMXm ์์นํ๊ณ ํธ๋ฒ๋งํฉ๋๋ค.
- ์๋๋ก - XNUMXm ๋จ์ด์ง๊ณ ์ผ์ด ๋ถ์ต๋๋ค.
- ์ผ์ชฝ์ผ๋ก-์ผ์ชฝ์ผ๋ก XNUMXm ์ด๋ํฉ๋๋ค.
- ์ค๋ฅธ์ชฝ์ผ๋ก-์ค๋ฅธ์ชฝ์ผ๋ก XNUMXm ์ด๋ํฉ๋๋ค.
- ํ์ - ์๊ณ ๋ฐฉํฅ์ผ๋ก 90๋ ํ์ ํฉ๋๋ค.
- ์์ผ๋ก - XNUMXm ์์ผ๋ก ๋์๊ฐ๋๋ค.
- ๋ค๋ก - ๋ฐ ๋ฏธํฐ ๋ค๋ก ๋์๊ฐ๋๋ค.
- ๋ฉ์ถ๋ค.
๋ค์์ ๋ช ๋ น์ ์๋ฝํ๊ณ , ํํฐ๋งํ๊ณ , ๋๋ก ์ ์ ์ดํ ์ ์๋ ์ฝ๋์ ๋๋ค.
const express = require('express');
const bodyparser = require('body-parser');
var arDrone = require('ar-drone');
const router = express.Router();
const app = express();
const commands = ['takeoff', 'land','up','down','goleft','goright','turn','goforward','gobackward','stop'];
var drone = arDrone.createClient();
// disable emergency
drone.disableEmergency();
// express
app.use(bodyparser.json());
app.use(express.static(__dirname + '/public'));
router.get('/',(req,res) => {
res.sendFile('index.html');
});
router.post('/command',(req,res) => {
console.log('command recieved ', req.body);
console.log('existing commands', commands);
let command = req.body.command.replace(/ /g,'');
if(commands.indexOf(command) !== -1) {
switch(command.toUpperCase()) {
case "TAKEOFF":
console.log('taking off the drone');
drone.takeoff();
break;
case "LAND":
console.log('landing the drone');
drone.land();
break;
case "UP":
console.log('taking the drone up half meter');
drone.up(0.2);
setTimeout(() => {
drone.stop();
clearTimeout();
},2000);
break;
case "DOWN":
console.log('taking the drone down half meter');
drone.down(0.2);
setTimeout(() => {
drone.stop();
clearTimeout();
},2000);
break;
case "GOLEFT":
console.log('taking the drone left 1 meter');
drone.left(0.1);
setTimeout(() => {
drone.stop();
clearTimeout();
},1000);
break;
case "GORIGHT":
console.log('taking the drone right 1 meter');
drone.right(0.1);
setTimeout(() => {
drone.stop();
clearTimeout();
},1000);
break;
case "TURN":
console.log('turning the drone');
drone.clockwise(0.4);
setTimeout(() => {
drone.stop();
clearTimeout();
},2000);
break;
case "GOFORWARD":
console.log('moving the drone forward by 1 meter');
drone.front(0.1);
setTimeout(() => {
drone.stop();
clearTimeout();
},2000);
break;
case "GOBACKWARD":
console.log('moving the drone backward 1 meter');
drone.back(0.1);
setTimeout(() => {
drone.stop();
clearTimeout();
},2000);
break;
case "STOP":
drone.stop();
break;
default:
break;
}
}
res.send('OK');
});
app.use('/',router);
app.listen(process.env.port || 3000);
๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์ ์ฌ์ฉ์์ ๋ง์ ๋ฃ๊ณ ๋ ธ๋ ์๋ฒ์ ๋ช ๋ น์ ๋ณด๋ด๋ HTML ๋ฐ JavaScript ์ฝ๋๊ฐ ์์ต๋๋ค.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Voice Controlled Notes App</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/shoelace-css/1.0.0-beta16/shoelace.css">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Voice Controlled Drone</h1>
<p class="page-description">A tiny app that allows you to control AR drone using voice</p>
<h3 class="no-browser-support">Sorry, Your Browser Doesn't Support the Web Speech API. Try Opening This Demo In Google Chrome.</h3>
<div class="app">
<h3>Give the command</h3>
<div class="input-single">
<textarea id="note-textarea" placeholder="Create a new note by typing or using voice recognition." rows="6"></textarea>
</div>
<button id="start-record-btn" title="Start Recording">Start Recognition</button>
<button id="pause-record-btn" title="Pause Recording">Pause Recognition</button>
<p id="recording-instructions">Press the <strong>Start Recognition</strong> button and allow access.</p>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="script.js"></script>
</body>
</html>
๋ํ ์์ฑ ๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๋ ธ๋ ์๋ฒ๋ก ๋ณด๋ด๋ JavaScript ์ฝ๋๋ ์์ต๋๋ค.
try {
var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
var recognition = new SpeechRecognition();
}
catch(e) {
console.error(e);
$('.no-browser-support').show();
$('.app').hide();
}
// other code, please refer GitHub source
recognition.onresult = function(event) {
// event is a SpeechRecognitionEvent object.
// It holds all the lines we have captured so far.
// We only need the current one.
var current = event.resultIndex;
// Get a transcript of what was said.
var transcript = event.results[current][0].transcript;
// send it to the backend
$.ajax({
type: 'POST',
url: '/command/',
data: JSON.stringify({command: transcript}),
success: function(data) { console.log(data) },
contentType: "application/json",
dataType: 'json'
});
};
์ ํ๋ฆฌ์ผ์ด์ ์คํ
ํ๋ก๊ทธ๋จ์ ๋ค์๊ณผ ๊ฐ์ด ์์ํ ์ ์์ต๋๋ค(์ฝฅํฐ๊ฐ Wi-Fi์ ์ฐ๊ฒฐ๋์ด ์๊ณ ์ด๋๋ท ์ผ์ด๋ธ์ด ์ปดํจํฐ์ ์ฐ๊ฒฐ๋์ด ์๋์ง ํ์ธํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค).
๋ธ๋ผ์ฐ์ ์์ localhost:3000์ ์ด๊ณ ์ธ์ ์์์ ํด๋ฆญํฉ๋๋ค.
์ฐ๋ฆฌ๋ ๋๋ก ์ ์ ์ดํ๋ ค๊ณ ๋
ธ๋ ฅํ๊ณ ํ๋ณตํฉ๋๋ค.
๋๋ก ์ผ๋ก ์์ ๋ฐฉ์กํ๊ธฐ
ํ๋ก์ ํธ์์ ์ ํ์ผ์ ๋ง๋ค๊ณ ์ฌ๊ธฐ์ ๋ค์ ์ฝ๋๋ฅผ ๋ณต์ฌํฉ๋๋ค.
const http = require("http");
const drone = require("dronestream");
const server = http.createServer(function(req, res) {
require("fs").createReadStream(__dirname + "/public/video.html").pipe(res);
});
drone.listen(server);
server.listen(4000);
์ฌ๊ธฐ์ HTML ์ฝ๋๊ฐ ์์ต๋๋ค. ์ด๋ฅผ ๊ณต์ฉ ํด๋์ ๋ฃ์ต๋๋ค.
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Stream as module</title>
<script src="/dronestream/nodecopter-client.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<h1 id="heading">Drone video stream</h1>
<div id="droneStream" style="width: 640px; height: 360px"> </div>
<script type="text/javascript" charset="utf-8">
new NodecopterStream(document.getElementById("droneStream"));
</script>
</body>
</html>
์ ๋ฉด ์นด๋ฉ๋ผ์ ๋น๋์ค๋ฅผ ๋ณด๋ ค๋ฉด localhost:8080์ ์คํํ๊ณ ์ฐ๊ฒฐํ์ธ์.
์ ์ฉํ ํ
- ์ด ๋๋ก ์ ์ค๋ด์์ ์กฐ์ข ํด๋ณด์ธ์.
- ์ด๋ฅํ๊ธฐ ์ ์ ํญ์ ๋๋ก ์ ๋ณดํธ ์ปค๋ฒ๋ฅผ ์์์ฃผ์ธ์.
- ๋ฐฐํฐ๋ฆฌ๊ฐ ์ถฉ์ ๋์ด ์๋์ง ํ์ธํ์ธ์.
- ๋๋ก ์ด ์ด์ํ๊ฒ ํ๋ํ๋ฉด ๋๋ก ์ ์ก๊ณ ๋ค์ง์ผ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ํฌ๋ฆฌ์ฝฅํฐ๊ฐ ๋น์ ๋ชจ๋๋ก ์ ํ๋๊ณ ๋กํฐ๊ฐ ์ฆ์ ์ ์ง๋ฉ๋๋ค.
์ค๋น๋ ์ฝ๋ ๋ฐ ๋ฐ๋ชจ
๊ทธ๊ฒ์ ๋์๋ค!
์ฝ๋๋ฅผ ์์ฑํ๊ณ ๊ธฐ๊ณ๊ฐ ๋ณต์ข ํ๊ธฐ ์์ํ๋ ๊ฒ์ ์ง์ผ๋ณด๋ ๊ฒ์ ์ฌ๋ฌ๋ถ์๊ฒ ์ฆ๊ฑฐ์์ ์ค ๊ฒ์ ๋๋ค! ์ด์ ์ฐ๋ฆฌ๋ ๋๋ก ์ด ์์ฑ ๋ช ๋ น์ ๋ฃ๋๋ก ๊ฐ๋ฅด์น๋ ๋ฐฉ๋ฒ์ ์์๋์ต๋๋ค. ์ค์ ๋ก ์ฌ์ฉ์ ์ผ๊ตด ์ธ์, ์์จ ๋นํ, ๋์ ์ธ์ ๋ฑ ํจ์ฌ ๋ ๋ง์ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.
ํ๋ก๊ทธ๋จ ๊ฐ์ ์ ์ํด ๋ฌด์์ ์ ์ํ ์ ์๋์?
Skillbox๋ ๋ค์์ ๊ถ์ฅํฉ๋๋ค.
- ์จ๋ผ์ธ ๊ฐ์ข ์ ์ฉ
"ํ์ด์ฌ ๋ฐ์ดํฐ ๋ถ์๊ฐ" .- ์จ๋ผ์ธ ์ฝ์ค
"์ง์ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์" .- ์ค๊ธฐ ์ฝ์ค
"0์์ PRO๋ก์ PHP ๊ฐ๋ฐ์" .
์ถ์ฒ : habr.com