친구 따라가기
하나의 컴퓨터에서 두 대의 햄스터 로봇을 제어하여 지난 시간에 배운 친구 따라가기를 다시 해봅시다.
하나의 컴퓨터에서 두 대의 햄스터 로봇을 사용하기 위해서는
컴퓨터에 동글을 두 개 꽂고 코드에서 hamster_create() 함수를 두 번 호출하면 됩니다.
Hamster* hamster1 = hamster_create();
Hamster* hamster2 = hamster_create();
여러 대의 햄스터 로봇을 제어하기 위해서는 haster_create() 함수가 반환하는 포인터를 사용하여 각각의 함수를 호출하면 됩니다.
지금까지 사용한
hamster_로 시작하는 함수들은 한 대의 햄스터 로봇(여러 대의 햄스터 로봇인 경우에는 첫 번째 햄스터 로봇)을 제어하기 위한 함수입니다.
hamster_로 시작하는 함수와 포인터를 통해 호출하는 함수는 형태가 같으며 다음 예시들과 같은 규칙을 가집니다.
|
한 대의 햄스터 로봇을 제어하기 위한 함수 |
여러 대의 햄스터 로봇 각각을 제어하기 위한 함수 |
인스턴스 생성 및 통신 연결 |
hamster_create(); |
Hamster* robot = hamster_create(); |
바퀴 제어 |
hamster_wheels(30, 30); |
robot->wheels(30, 30); |
왼쪽 근접 센서 |
hamster_left_proximity() |
robot->left_proximity() |
오른쪽 바닥 센서 |
hamster_right_floor() |
robot->right_floor() |
이 외의 다른 함수들도 같은 규칙으로 함수 이름이 정해져 있습니다.
각각의 햄스터 로봇이 전방을 살펴보면서 검은색 선을 따라 주행하는 코드는 다음과 같이 작성될 수 있습니다.
#include "roboid.h"
int main(int argc, char *argv[]) {
int diff;
Hamster* hamster1 = hamster_create();
Hamster* hamster2 = hamster_create();
while(1) {
// 첫 번째 햄스터 로봇
if(hamster1->left_proximity() > 50 || hamster1->right_proximity() > 50) {
hamster1->stop();
} else {
diff = hamster1->left_floor() - hamster1->right_floor();
hamster1->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
// 두 번째 햄스터 로봇
if(hamster2->left_proximity() > 50 || hamster2->right_proximity() > 50) {
hamster2->stop();
} else {
diff = hamster2->left_floor() - hamster2->right_floor();
hamster2->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
return 0;
}
같은 코드를 두 번 작성하였기 때문에 뭔가 비효율적으로 보입니다.
햄스터 로봇의 수가 많아지면 어떻게 될까요?
함수로 만드는 것이 좋겠습니다.
#include "roboid.h"
void trace(Hamster* hamster) {
if(hamster->left_proximity() > 50 || hamster->right_proximity() > 50) {
hamster->stop();
} else {
int diff = hamster->left_floor() - hamster->right_floor();
hamster->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
}
int main(int argc, char *argv[]) {
Hamster* hamster1 = hamster_create();
Hamster* hamster2 = hamster_create();
while(1) {
trace(hamster1); // 첫 번째 햄스터 로봇
trace(hamster2); // 두 번째 햄스터 로봇
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
return 0;
}
이제 햄스터 로봇의 수가 많아져도 hamster_create() 함수를 호출하는 부분과 trace() 함수를 호출하는 부분만 추가하면 되기 때문에 훨씬 간단해졌습니다.
첫 번째 햄스터 로봇의 전원만 켜고 코드를 실행한 후 잠시 후에 두 번째 햄스터 로봇의 전원을 켜보도록 합시다.
어떻게 되나요?
첫 번째 햄스터 로봇이 통신으로 연결되었을 때 동작을 먼저 시작하게 됩니다.
두 번째 햄스터 로봇의 전원을 켜서 모든 로봇이 통신으로 연결된 후 동작을 같이 시작하게 하려면
hamster_create() 함수를 호출한 후에 wait_until_ready() 함수를 호출해 주면 됩니다.
#include "roboid.h"
void trace(Hamster* hamster) {
if(hamster->left_proximity() > 50 || hamster->right_proximity() > 50) {
hamster->stop();
} else {
int diff = hamster->left_floor() - hamster->right_floor();
hamster->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
}
int main(int argc, char *argv[]) {
Hamster* hamster1 = hamster_create();
Hamster* hamster2 = hamster_create();
wait_until_ready();
while(1) {
trace(hamster1); // 첫 번째 햄스터 로봇
trace(hamster2); // 두 번째 햄스터 로봇
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
return 0;
}
참고로, 배열을 사용하여 좀 더 일반적인 형태로 수정하면 다음과 같이 됩니다.
#include "roboid.h"
#define NUM_HAMSTERS 2 // 햄스터의 수를 변경하기 위해서는 숫자 2만 수정하면 된다.
void trace(Hamster* hamster) {
if(hamster->left_proximity() > 50 || hamster->right_proximity() > 50) {
hamster->stop();
} else {
int diff = hamster->left_floor() - hamster->right_floor();
hamster->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
}
int main(int argc, char *argv[]) {
Hamster* hamsters[NUM_HAMSTERS];
int i;
for(i = 0; i < NUM_HAMSTERS; ++i) {
hamsters[i] = hamster_create();
}
wait_until_ready();
while(1) {
for(i = 0; i < NUM_HAMSTERS; ++i) {
trace(hamsters[i]);
}
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
return 0;
}
쇼트 트랙 릴레이
마찬가지로 하나의 컴퓨터에서 두 대의 햄스터 로봇을 제어하여 지난 시간에 배운 쇼트 트랙 릴레이를 다시 해봅시다.
#include "roboid.h"
void trace(Hamster* hamster) {
if(hamster->left_proximity() > 50 || hamster->right_proximity() > 50) {
hamster->stop();
} else {
int diff = hamster->left_floor() - hamster->right_floor();
hamster->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
}
int calc_speed(int proximity) {
if(proximity > 60) {
return 0;
} else {
return (int)((60 - proximity) * 0.8);
}
}
void chase(Hamster* hamster) {
int left_speed = calc_speed(hamster->left_proximity());
int right_speed = calc_speed(hamster->right_proximity());
hamster->wheels(left_speed, right_speed);
}
int main(int argc, char *argv[]) {
Hamster* hamster1 = hamster_create();
Hamster* hamster2 = hamster_create();
wait_until_ready();
while(1) {
trace(hamster1); // 첫 번째 햄스터 로봇
chase(hamster2); // 두 번째 햄스터 로봇
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
return 0;
}
USB 동글을 꽂는 위치에 따라 선두 로봇과 뒤따라가는 로봇의 순서가 바뀔 수 있습니다.
이 경우에는 다음과 같이 선두 로봇과 뒤따라가는 로봇을 서로 바꾸어 주면 됩니다.
while(1) {
trace(hamster2); // 첫 번째 햄스터 로봇
chase(hamster1); // 두 번째 햄스터 로봇
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
선두 로봇과 뒤따라가는 로봇을 고정시키기 위해서는 다음과 같이 hamster_create_port() 함수를 사용하여 시리얼 포트 이름을 지정해 주어도 됩니다.
(
클라우드 컴퓨터 환경에서 작업하기 참고)
#include "roboid.h"
void trace(Hamster* hamster) {
if(hamster->left_proximity() > 50 || hamster->right_proximity() > 50) {
hamster->stop();
} else {
int diff = hamster->left_floor() - hamster->right_floor();
hamster->wheels(30 + diff * 0.4, 30 - diff * 0.4);
}
}
int calc_speed(int proximity) {
if(proximity > 60) {
return 0;
} else {
return (int)((60 - proximity) * 0.8);
}
}
void chase(Hamster* hamster) {
int left_speed = calc_speed(hamster->left_proximity());
int right_speed = calc_speed(hamster->right_proximity());
hamster->wheels(left_speed, right_speed);
}
int main(int argc, char *argv[]) {
Hamster* hamster1 = hamster_create_port("COM57");
Hamster* hamster2 = hamster_create_port("COM70");
wait_until_ready();
while(1) {
trace(hamster1); // 첫 번째 햄스터 로봇
chase(hamster2); // 두 번째 햄스터 로봇
wait(10); // 너무 빨리 반복하지 않도록 한다.
}
return 0;
}
목차
고급
- 행위 기반의 로봇 제어
- 경로 탐색
- 자리 바꾸기
Copyright 로봇SW교육원 All rights reserved.
어려운 일이 있으면 광운대학교 로봇학부 박광현 교수(
akaii@kw.ac.kr)에게 연락하세요.