기본적인 Java 문법에서 객채기반 프로그래밍까지
JD5
2 ) 5 S xcs
JD5 2 )
http://www.lejos.org/ev3.php
Java를 사용하여 EV3를 제어할수 있는 소프트웨어 EV3 상에서 구동되는 Java Virtual Machine
Windows, Mac, Linux에서 모두 사용 가능
기본적인 모터제어, 센서 사용부터 PAN을 이용한 16개 EV3의 데이지 체이닝, OpenCV 2.4 사용 영상처리, 커스텀 센서 사용 (IMU, LIDAR등) 같은 고급적인 제어도 할수 있다.
JD5 2 ) 3 O T OD
IDE 소프트웨어 이클립스
로봇 프로그램
펌웨어에서 구동될 로봇 코드 작성, 컴파일 및 배포
leJOS Firmware가 설치된 EV3 P-Brick USB, WiFi, Bluetooth
JD5 2 ) 3 O T OD (
leJOS Firmware가 설치된 EV3 P-Brick
센서 / 로봇 데이터
Ex) 인코더 값, 적외선 센서 값 로봇을 어떻게 제어할건지 P-지령
Brick 상에서 계산하여 제어
EV3 모터, 센서
2BJ NPD
Java를 사용하여 짜기 위한 IDE (통합개발환경) 프로그램
산업현장에서 Java 프로그래밍을 할때 제일 많이 사용하는 프로그램 leJOS 사용을 위한 Add-On이 개발되어 있어 간단히 leJOS 사용을 시 작할수 있다
Windows / Mac OS X 무료
neon 32 bit 에서 프로그램 가능함
5 S 2 2 ADCCDC
http://www.oracle.com/technetwork/java/embedded/embedded-se/
leJOS 펌웨어의 기반
저용량 Java Virtual Machine을 임베디드 시스템에서 사용하여 프로 그래밍 할수 있게 한다
1-1. leJOS 프로그램 설치
1-2. Eclipse와 Eclipse 플러그인 설치 1-3. EV3와 USB 연결 프로그램 설치 1-4. 프로그램 작성
1-5. 1초 직진하는 로봇
JD5 2 ) 3 O T OD d 5 S V U
JD5 xct
4GB MicroSD 카드 구매 (32GB 지원 안됨) MicroSD – USB 어답터 필요
JD5 xct
구글에 “jdk 7 download” 친 후 “Java SE Development Kit 7 – Downloads” 링크로 들어간다
Accept를 누르고 아래 JDK를 다운받는다
자신의 운영 체제에 맞는 JDK 7을 다운받은후 설치한다
64bit 다운 받음: 이것 안됨 반드시 주어된 것 x86를 받을 것
JD5 xct
https://sourceforge.net/projects/ev3.lejos.p/files/
위 링크에서 최신 파일의 leJOS_EV3_버젼_win32_setup.exe 파일 다운
JD5 xct
다운받은 파일 실행
Java JDK 7을 설치했으면 jdk1.7…..같은 폴더가 있을것이다. 클릭한후 다음으로 넘어간다.
64비트 디렉토리 선택 해줌
JD5 xct
계속 설치를 진행한다.
JD5 xct
끝나면 Launch EV3SDCard utility 버튼을 클릭하고 Finish를 누른다.
JD5 xct
https://www.sdcard.org/downloads/formatter_4/
위 링크에 들어가 SD Formatter 4.0을 다운받은 후, Micro SD 카드를 깨끗히 포맷해준다.
http://java.com/legomindstorms
그 후 위 링크에 들어가 “Oracle Java SE Embedded version 7”을 다 운받는다.
반드시 이것을 다운 받아야 함.
jdk 아님
JD5 xct
포맷한 SD 카드를 선택하고, 방금 다운로드 받은 ejre 파일을 선택한 후, Create 버튼을 누른다.
만들어진 후 Micro SD카드를 안전하게 추출한다.
sd card 선택
JD5 xct
Micro SD카드를 EV3 옆면에 삽입한후 전원 버튼을 2초정도 눌러준다.
leJOS가 SD카드에 설치되는 동안 Eclipse 개발환경을 구축하도록 하자.
이렇게 하니 되었음
[왼쪽키와 중앙키를 동시에 누르고 아주 오래 기다리면 "라리라" 소리가 나고 동작됨
( 2BJ NPD JD5 uc
구글에 “jre 7 download” 친 후 “Java SE Runtime Environment 7 - Downloads” 링크로 들어간다
Accept를 누르고 아래 JRE를 다운받는다
자신의 운영 체제에 맞는 JRE 7을 다운받은후 설치한다
최신판 받으면 안되요.
반드시 지정된 것 바운 받아요.
( 2BJ NPD JD5 uc
https://www.eclipse.org/downloads/
위 링크에 들어가 자신의 운영체제에 맞는 Eclipse IDE for Java Developers를 다운받아 설치한다.
( 2BJ NPD JD5 uc
Eclipse를 설치한 후 Help -> Install New Software -> Add 클릭
여기서 문제 발생 : Chrome Browser에서 Eclipse Marketplace치고 여기서 설치 해야됨.
( 2BJ NPD JD5 uc
Eclipse에 끌어다 놓으면 된다.
( 2BJ NPD JD5 uc
Preferences에 들어가 아래와 같이 설정한다.
window/preference/Java/leJOS EV3
) 2 ) / xct
SD카드를 삽입한 EV3의 전원을 킨 후 USB로 컴퓨터에 연결한다 장치 관리자를 연다
RNDIS / Ethernet 부분을 우클릭한후 드라이버 업데이트를 진행한다 EV3를 가상 Ethernet 선으로 인식하게 하여 와이파이 연결 없이 유 선상으로 연결하는 방법
이때 EV3의 IP주소는 10.0.1.1이다
) 2 ) ? 3 x d
WiFi 동글을 EV3에 연결한후 EV3에서 WiFi 탭에 들어가 인터넷에 연 결한다.
leJOS 메인 화면에서 IP주소를 확인한다.
컴퓨터를 EV3와 같은 네트워크에 연결한다.
Eclipse의 설정화면에 들어가 EV3의 IP주소를 입력한다.
xct
새로운 LeJOS EV3 Project를 만든다
xct
다음과 같이 설정한다.
xct
JavaEV3 프로젝트에서 새로운 클래스를 만든다
xct ,
알고리즘: 문제를 해결하기 위한 동작들의 모임 / 순서도 Method: 어느 ‘행동’을 하는 프로그램
Source Code: 프로그램을 짠 원본 코드
g x
1초동안 직진하는 로봇을 만들어보자.
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전)
1초 기다린다
모터 B, C에 파워를 끊는다 모터가 움직인다고 출력한다
g x
OneSecond.java 파일이 열리면 지운 후 위 코드를 입력한다.
이미 작성된 프로그램을 작성하는 프로그램에서 이용하기 위해 불러오는 과정 leJOS 라이브러리를 사용하기 위해 불러들인다
import lejos.hardware.motor.*;
import lejos.hardware.port.*;
import lejos.utility.Delay;
g x
Class는 Java에서 함수들, 객채들의 구조를 성립하는데 사용된다 추후에 더 알아보기로 하자
import lejos.hardware.motor.*;
import lejos.hardware.port.*;
import lejos.utility.Delay;
public class OneSecond {
}
g x
Main Loop은 프로그램이 실행되는 부분이며, 한 프로그램에 하나만 있을수 있다.
1, 2강에서 작성되는 모든 코드는 이 메인 룹 안 에서 작동한다.
import lejos.hardware.motor.*;
import lejos.hardware.port.*;
import lejos.utility.Delay;
public class OneSecond {
public static void main(String[] args) { }
}
g x
로봇을 제어하는 코드는 메인 룹 안에 들어간다.
모든 줄의 끝에는 세미콜론 (;)을 붙혀 새로운 줄 을 시작한다는것을 알려줘야 한다
글귀는 “” 안에 들어가야 한다.
import lejos.hardware.motor.*;
import lejos.hardware.port.*;
import lejos.utility.Delay;
public class OneSecond {
public static void main(String[] args) {
EV3LargeRegulatedMotor motorL = new EV3LargeRegulatedMotor(MotorPort.B);
EV3LargeRegulatedMotor motorR = new EV3LargeRegulatedMotor(MotorPort.C);
System.out.println("Robot Moving");
motorL.setSpeed(360);
motorR.setSpeed(360);
motorL.forward();
motorR.forward();
Delay.msDelay(1000);
motorL.stop(true);
motorR.stop(true);
motorL.close();
motorR.close();
} }
g x
프로그램은 적힌 순서대로, 위에서 아래로 실행된다.public static void main(String[] args) {
EV3LargeRegulatedMotor motorL = new EV3LargeRegulatedMotor(MotorPort.B);
EV3LargeRegulatedMotor motorR = new EV3LargeRegulatedMotor(MotorPort.C);
System.out.println("Robot Moving");
motorL.setSpeed(360);
motorR.setSpeed(360);
motorL.forward();
motorR.forward();
Delay.msDelay(1000);
motorL.stop(true);
motorR.stop(true);
motorL.close();
motorR.close();
}
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전)
1초 기다린다
모터 B, C에 파워를 끊는다 모터가 움직인다고 출력한다
g x D FMCP
EV3LargeRegulatedMotor
motorL
=new
EV3LargeRegulatedMotor(MotorPort.B):B포트에 있는 모터 객체 (object) 를 생성하는 방법 (객체, 생성은 추후에 설명) (MotorPort.A, MotorPort.C, MotorPort.D)
System.out.println("Robot Moving");
: 새로운 줄에 글귀를 출력하는 방법. “ ” 안에 글귀를 입력하면 된다.
Delay.msDelay(1000): 괄호 속 숫자만큼의 ms동안 기다리는 함수 (1000ms = 1sec)
motorL.setSpeed(360);
: motorL의 기본 속도를 1초에 360도 회전하게 (60RPM) 설정한다.
motorL.forward();
: motorL을 기본 속도로 정방향으로 회전하게 한다.
motorL.stop(true);
: motorL을 바로 정지시킨다.
motorL.close();: 객채에 할당된 리소스를 닫는다.
g x
OneSecond.java를 우클릭하여 Run As > 2 leJOS EV3 Program 클릭 프로그램이 실행되는 것을 관찰한다.
2-1. 충돌을 하면 자동으로 멈추는 로봇 2-2. 장애물 탐지 로봇
2-3. 라인트레이싱 로봇
2-4. 터치센서가 눌린 횟수를 세는 로봇 2-5. 변수, 조건문, 연산자, 반복문 사용 연습하기
( 2 ) c M PMJD
( l m x g x
직진을 하다 벽과 충돌을 하면 자동으로 멈추는 로봇을 만들어 보자.
터치센서를 사용하여 충돌을 감 지해보자.
벽과 충돌했는가?
(터치센서 값이 1인가?)
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전) 모터가 움직인다고 출력한다
모터 B, C에 파워를 끊는다
( l m x g x
1-5의 코드와 2-1의 코드는 아래 부분만 다르다. 1-5의 코드를 약간 수정하여 충돌을 하면 자동으로 멈추는 로봇을 만들어보자.
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전)
1초 기다린다
모터 B, C에 파워를 끊는다 모터가 움직인다고 출력한다
벽과 충돌했는가?
(터치센서 값이 1인가?)
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전) 모터가 움직인다고 출력한다
모터 B, C에 파워를 끊는다
( JD5 D PMO 3O DTMOI
대기측정 센서 대기
샘플 값 분석 리포트
| 미세먼지 | 온도 | 습도 | 산소 농도 | …. |
대기 샘플
필요한 센서 값 추출하여 사용
대기 샘플 추출
( JD5 D PMO 3O DTMOI
센서 주변 환경
센서 값 배열 float[]
| value0 | value1 | value2 | … |
센서값 샘플 데이터 SampleProvider
필요한 센서 값 추출하여 사용
환경 샘플 추출
( JD5 D PMO 3O DTMOI
터치센서
눌렸는가? 안눌렸는가?
센서 값 배열 float[] touchValue
| value0 |
센서값 샘플 데이터
SampleProvider touchSample touchValue[0]
fetchSample(touchValue, 0);
반복
(
센서 셋업 과정 EV3TouchSensor
touch
= new EV3TouchSensor(SensorPort.S1);
//터치센서 생성
SampleProvider
touchSample
=touch.getTouchMode();
//어떤 샘플을 가져올건지 고른다 (0이면 안눌림, 1이면 눌림)
float[] touchValue
= new float[touch.sampleSize()];//센서 샘플 값을 저장하는 배열을 만든다
touchSample.fetchSample(touchValue, 0);
//샘플을 추출하여 그 분석값을 배열에 저장한다
touchValue[0]
//배열에서 원하는 값을 읽어들인다
touchValue[0] == 0
//터치센서 안눌림touchValue[0] == 1
//터치센서 눌림( d
먼저, 센서를 사용하니 센서 펌웨어를 import 하자. 맨 위에 아래 코드를 추가해주자.
import
lejos.hardware.sensor.*;import
lejos.robotics.SampleProvider;EV3TouchSensor
touch
= new EV3TouchSensor(SensorPort.S1);SampleProvider
touchSample
= touch.getTouchMode();float[] touchValue
=new float[touch.sampleSize()];
touchSample.fetchSample(touchValue, 0);
다음, 모터를 만들어주는 코드 다음 아래 코드를 추가해보자.
( l m x g x MROBD MCD
이제, “1초 기다린다” 라는 코드를, 아래 ”충돌할때까지 기다린다” 라는 코드로 바꾸자.
while(touchValue[0] == 0.0) {
touchSample.fetchSample(touchValue, 0);
}
Delay.msDelay(1000);
충돌 탐지 알고리즘
프로그램 종료 로봇 Initialization 과정
( l m x g x MROBD MCD
아래와 같은 코드가 작성되어 있을 것이다.
EV3LargeRegulatedMotor motorL = new EV3LargeRegulatedMotor(MotorPort.B);
EV3LargeRegulatedMotor motorR = new EV3LargeRegulatedMotor(MotorPort.C);
EV3TouchSensor touch = new EV3TouchSensor(SensorPort.S1);
SampleProvider touchSample= touch.getTouchMode();
float[] touchValue = new float[touch.sampleSize()];
touchSample.fetchSample(touchValue, 0);
System.out.println("Robot Moving");
motorL.setSpeed(360);
motorR.setSpeed(360);
motorL.forward();
motorR.forward();
while(touchValue[0] == 0.0) {
touchSample.fetchSample(touchValue, 0);
}
motorL.stop(true);
motorR.stop(true);
motorL.close();
motorR.close();
touch.close();
( l m x g x D FMCP
EV3TouchSensor
touch
= new EV3TouchSensor(SensorPort.S1);: EV3 터치센서 touch 객채를 생성하는 방법 System.out.println("Robot Moving");
: 새로운 줄에 글귀를 출력하는 방법. “ ” 안에 글귀를 입력하면 된다.
motorL.setSpeed(360);
: motorL의 기본 속도를 1초에 360도 회전하게 (60RPM) 설정한다.
motorL.forward();
: motorL을 기본 속도로 정방향으로 회전하게 한다.
motorL.stop(true);
: motorL을 바로 정지시킨다.
touch.close();
: 객채에 할당된 리소스를 닫는다.
( while
“터치센서 값이 0인 동안” :
touchValue[0] == 0
“터치센서 값을 읽는것을” :
touchSample.fetchSample(touchValue, 0);
“반복한다” :
while
while(touchValue[0] == 0) {
touchSample.fetchSample(touchValue, 0);
}
while(pushUpCount
< 10) { doPushUp();pushUpCount = pushUpCount + 1;
}
“팔굽혀펴기를 10번 할때까지” :
pushUpCount
< 10“팔굽혀펴기를” : doPushUp(); pushUpCount = pushUpCount + 1;
“반복한다” :
while
( while
: While 반복문은 소괄호 안의 condition(조건)이 true이면 중괄호 내부 프로그램을 반복한다. 소괄호 안의 조건이 false가 되는 순간 반복이 멈추고 반복문 다음 줄에 있는 명령을 실행한다.
: While 반복문 내에 아무 프로그램이 없으면 조건이 거짓이 될때까지 기다리는 효과를 지니게 된다.
: Boolean과 ‘==‘의 의미에 대해서는 다음 장에서 알아보도록 하자.
while(boolean
condition) { //프로그램 실행}
while(touchValue[0] == 0) {
//터치센서 값이 0이면 반복한다 //프로그램 실행touchSample.fetchSample(touchValue, 0);
}
( k l d
이제, 터치 센서를 누르면 1초간 전진을 시작하는 프로그램을 짜보자.
while 반복문은 어디에 쓰이는가?
소수/유리수를 나타내는 2가지 종류의 변수타입은 무엇인가? 센서 값 을 읽을때는 어떤 종류로 읽어지고, 변수를 선언하여 사용할때는 어 떤 종류를 사용해야 하는가?
참고--1초 기다리기: Delay.msDelay(1000);
( ( x
이번에는 충돌 전, 앞에 장애물이 있을때 멈추는 로봇을 만들어보자.
장애물이 사라지면 다시 움직이고, 혹시나 장애물과 충돌하면 멈춘 후 프로그래밍해보자.
초음파 센서는 앞에 있는 어느 물체와의 거리를 재는 센서이다.
크고 단단하며 평면적인 물체를 탐지하는데 효과적이다.
( ( x
이번에는 충돌 전, 앞에 장애물이 있을때 멈추는 로봇을 만들어보자.
모터 B, C에 파워를 끊는다 벽과 충돌했는가?
(터치센서 값이 1인가?)
모터 B, C에 파워를 끊는다 벽이 threshold보다 가까운가?
(초음파센서 값이 threshold보다 작은가?)
모터 B, C에 50만큼의 파워를 준다 모터가 움직인다고 출력한다
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전)
( ( x
아래 박스 부분이 장애물 탐지 알고리즘에서 추가되는 부분이다.
벽과 충돌했는가?
(터치센서 값이 1인가?)
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전) 모터가 움직인다고 출력한다
모터 B, C에 파워를 끊는다 모터 B, C에 파워를 끊는다
벽과 충돌했는가?
(터치센서 값이 1인가?)
모터 B, C에 파워를 끊는다 벽이 threshold보다 가까운가?
(초음파센서 값이 threshold보다 작은가?)
모터 B, C에 50만큼의 파워를 준다 모터가 움직인다고 출력한다
모터 B, C에 360만큼의 속력를 준다 (1초에 1회전)
( (
아래와 같이 새로운 클래스를 만들어보자.
( (
아래와 같이 새로운 클래스를 만들어보자.
( (
이제 박스부분의 알고리즘을 간단히 작성해보자.
ultrasonic: 가상의 초음파센서 값
( (
이번에는 방금 작성한 프로그램은 Java Application으로 실행해보자.
( (
초음파 센서의 값이 threshold의 값보다 작으니 로봇은 정지했다고
“STOP”이라고 출력한다.
threshold, ultrasonic의 값을 바꿔가면서 실행하여 어떤 결과가 있는지 확인해보자. “MOVE”라고 출력을 하기 위해서는 어떻게 하면 될까?
반복
( (
센서 셋업 과정 EV3UltrasonicSensor
ultrasonic
= new EV3UltrasonicSensor(SensorPort.
S2);
//초음파센서 생성
SampleProvider
usSample
= ultrasonic.getDistanceMode();//거리를 측정하는 모드로 설정한다 (미터)
float[] usValue
= new float[ultrasonic.sampleSize()];//센서 샘플 값을 저장하는 배열을 만든다
usSample.fetchSample(usValue, 0);
//샘플을 추출하여 그 분석값을 배열에 저장한다
usValue[0]
//배열에서 원하는 값을 읽어들인다
( ( x MROBD MCD
로봇 Initialization 과정
EV3LargeRegulatedMotor motorL = new EV3LargeRegulatedMotor(MotorPort.B);
EV3LargeRegulatedMotor motorR = new EV3LargeRegulatedMotor(MotorPort.C);
EV3TouchSensor touch = new EV3TouchSensor(SensorPort.S1);
EV3UltrasonicSensor ultrasonic = new EV3UltrasonicSensor(SensorPort.S2);
SampleProvider touchSample= touch.getTouchMode();
SampleProvider usSample= ultrasonic.getDistanceMode();
float[] touchValue = new float[touch.sampleSize()];
float[] usValue = new float[ultrasonic.sampleSize()];
touchSample.fetchSample(touchValue, 0);
usSample.fetchSample(usValue, 0);
double threshold = 0.2;
System.out.println("Robot Moving");
motorL.setSpeed(200);
motorR.setSpeed(200);
motorL.forward();
motorR.forward();
double threshold
= 0.2;( ( x MROBD MCD (
while(touchValue[0] == 0) { if
() {//모터 정지 }
else
{//모터 움직임 }
touchSample.fetchSample(touchValue, 0);
usSample.fetchSample(usValue, 0);
}
while(touchValue[0] == 0) {
touchSample.fetchSample(touchValue, 0);
}
usValue[0]
//배열에서 원하는 값을 읽어들인다
장애물 탐지 알고리즘
( ( x MROBD MCD (
프로그램 종료
while(touchValue[0] == 0) {
if (usValue[0] < threshold) { motorL.stop(true);
motorR.stop(true);
} else {
motorL.setSpeed(200);
motorR.setSpeed(200);
motorL.forward();
motorR.forward();
}
touchSample.fetchSample(touchValue, 0);
usSample.fetchSample(usValue, 0);
}
motorL.stop(true);
motorR.stop(true);
motorL.close();
motorR.close();
touch.close();
ultrasonic.close();
( ( boolean
전에 작성했었던 algorithmTest 프로그램에 아래 줄을 추가하고 실행시 켜보자.
( ( boolean
:
boolean은 참 (true, 1), 거짓 (false, 0)으로 나뉘는 변수의 종류이다.
: 참, 거짓의 조건들을 판명하는데 많이 사용된다.
: 반복문의 반복 조건으로도 사용된다.
boolean
condition = true;: 이렇게 boolean 변수를 선언한다.
터치센서
touchValue[0] == 0
안눌림 true
눌림 false
장애물 거리
usValue[0] < 0.2
가깝다 true
멀다 false
비교연산자
( ( if-else
: if-else 조건문은 소괄호 안의 condition(조건)이 true이면 if문의 프로그램을, false면 else문의 프로그램을 실행시킨다.
: 조건이 false일때 아무 프로그램도 실행되지 않아도 된다면 else문은 생략 가능하다.
: 그와 비슷하게, if와 else문 사이에 else if 조건을 추가할수 있다.
if
(boolean condition1) { //run program 1}
else if
(boolean condition2) { //run program 2}
else
{//run program 3 }
if
(boolean condition) { //run program 1}
if
(boolean condition) { //run program 1}
else
{//run program 2 }
( ( a
!=
<=
<
x y
>
>=
==
부등호가 참이면 true 부등호가 거짓이면 false 같지 않다
같다
x = 6 y = 5
x = 5 y = 5
x = 4 y = 5
비교연산자는 두가지의 값을 비교하여 boolean 값을 반환한다.
아래의 6가지 종류가 있다. (부등호의 개념으로 생각!)
( ( a boolean
if
(usValue[0] < threshold) { //Run ProgramusSample.fetchSample(usValue
, 0);}
boolean tooClose
= usValue[0] < threshold;if
(tooClose) { //Run ProgramusSample.fetchSample(usValue, 0);
tooClose
= usValue[0] < threshold;}
아래 두개의 코드는 똑같이 작동한다.
( ( x , n d
현재 코드에서는 setSpeed() method를 여러번 사용하고 있다
모터가 멈춰있을때만 P-Brick이 모터에 지령을 내리게 코드를 수정해 보자.
motorB.isMoving ()
: 모터가 현재 켜져있는지 꺼져있는지 확인하는 메서드.
켜져있으면 true, 꺼져있으면 false를 반환한다.
while(touchValue[0] == 0.0) {
if (usValue[0] < threshold) { motorL.stop(true);
motorR.stop(true);
} else {
if (!motorL.isMoving() && !motorR.isMoving()) { motorL.setSpeed(200);
motorR.setSpeed(200);
motorL.forward();
motorR.forward();
} }
touchSample.fetchSample(touchValue, 0);
usSample.fetchSample(usValue, 0);
}
( ( e . 1, A && B
button1 = true button2 = true (button1 && button2) = true
button1 = true button2 = false (button1 && button2) = false
( ( e :, A || B
fire1 = true fire2 = false fire3 = false
(fire1 || fire2 || fire3) = true
boolean fire1 = true;
boolean fire2 = false;
boolean fire3 = false;
if (fire1 && fire2 && fire3) {
System.out.println("CASE 1 DETECTED");
}
if (fire1 || fire2 || fire3) {
System.out.println("CASE 2 DETECTED");
}
( ( k l d
이제, 장애물이 0.5m 거리에 있으면 느려지고, 0.3m 거리에 있으면 정지하며, 장애물이 사라졌을때 다시 움직이고, 충돌하면 멈추는 로봇 을 프로그래밍 해보자.
double
close,double
tooClose 두가지의 변수를 선언하여 프 로그래밍하자.어느 순서로 조건을 확인해야 할까?
if-else 조건문은 어디에 쓰이는가?
boolean는 어떤 변수인가? 어느 값을 가질수 있는가?
( ) v x
이번에는 검은 선을 따라가는 라인트레이서 로봇을 프로그래밍 하자.
컬러 센서의 반사광 모드를 사용하여 흰 바닥과 검은 선을 분간하자 검은 선을 따라가다가 장애물과 충돌하면 멈추게 하자
검은 선이 보이면 좌측으로, 흰 선이 보이면 우측으로 회전하게 하자
라인을 따라가는 로봇
도착 출발
컬러센서 위치
( ) v x
라인을 따라가는 로봇
도착 출발
컬러센서 위치( ) v x
다음은 빛센서 위치에 따른 예제 반삿값이다.
0.35 0.20
0.10 0.04
빛센서 위치
( ) v x
0.50
( ) v x D FMC
검은색 선 위에 있을때 반사값과 흰색 바닥의 반삿값의 평균을 내어 문턱값으로 설정하자.
먼저, 아래 메서드들을 이용해 컬러 센서의 반삿값을 1초에 1번씩 5 번 P-Brick 스크린에 출력하는 프로그램을 짜보아 흰색, 검정색의 반 삿값을 구해보자.
EV3ColorSensor
color
= new EV3ColorSensor(SensorPort.S3);
SampleProvider
colorSample
=color.getRedMode();
float[] colorValue
= new float[color.sampleSize()];: EV3 컬러센서 color 객채를 생성하는 방법 (반사광 모드)
( ) for
위 두개의 코드는 같은 결과를 출 력한다.
똑같은 logic / 프로그램을 유한번 반복하여 실행해야 할때 for 룹을 사용한다.
for (int count = 1; count <= 5; count++) { colorSample.fetchSample(colorValue, 0);
System.out.println("Number " + count + ": " + colorValue[0]);
Delay.msDelay(1000);
}
Delay.msDelay(5000);
colorSample.fetchSample(colorValue, 0);
System.out.println("Number 1: "+ colorValue[0]);
Delay.msDelay(1000);
colorSample.fetchSample(colorValue, 0);
System.out.println("Number 2: "+ colorValue[0]);
Delay.msDelay(1000);
colorSample.fetchSample(colorValue, 0);
System.out.println("Number 3: "+ colorValue[0]);
Delay.msDelay(1000);
colorSample.fetchSample(colorValue, 0);
System.out.println("Number 4: "+ colorValue[0]);
Delay.msDelay(1000);
colorSample.fetchSample(colorValue, 0);
System.out.println("Number 5: "+ colorValue[0]);
Delay.msDelay(1000);
Delay.msDelay(5000);
( ) for
초기화 단계에서는 반복문의 조건을 맞추는데 사용될 변수의 초기 값 을 정한다.
조건 단계에서는 변수를 반복이 멈출때의 조건과 비교한다. 비교연산 자 값이 true가 될때까지 반복한다.
반복 단계에서는 변수의 값을 변환해준다 (count++, count--, count = count + 2…)
for
(inti
= 0; i < 5;i++) {
//Run Program}
for
(initialization_초기화; condition_조건; afterthought_반복) { //Run Program}
( ) v x
다음, 구한 문턱값을 사용하여 아래 로직을 따라 라인트레이싱 프로 그램을 완성해보자.
while
(!collided) {if
(sensor_value > threshold) { //왼쪽 모터 더 빨리 회전}
else
{//오른쪽 모터 더 빨리 회전 }
}
( ) v x MROBD MCD
double midpoint = 0.28;
while(touchValue[0] == 0) {
if (colorValue[0] > midpoint) { motorL.setSpeed (300);
motorR.setSpeed (50);
motorL.forward();
motorR.forward();
} else {
motorL.setSpeed (50);
motorR.setSpeed (300);
motorL.forward();
motorR.forward();
}
touchSample.fetchSample(touchValue, 0);
colorSample.fetchSample(colorValue, 0);
}
motorL.stop();
motorR.stop();
motorL.close();
motorR.close();
touch.close();
color.close();
( ) k l d
이제는 장애물이 있으면 정지하고, 장애물이 없을때는 검은 선을 따 라가다가 혹시 벽과 충돌하면 영원히 정지하게 프로그래밍해보자.
for 반복문은 어디에 쓰이는가?
for 반복문을 쓰기 위해서는 어떤 조건들을 입력해야 하는가?
( W g x
5초동안 터치센서가 몇번 눌렸는지 확인할수 있는 로봇을 프로그래 밍해보자.
시작할때 P-Brick에서 시작한다는 소리가 울리고
끝난후 소리가 울린후 화면에 몇회 눌렸다고 출력이 된 후 5초 후에 프로그램 종료
아래 방법과 다음 페이지의 메서드들을 사용해서 프로그램을 작성해 보자.
몇번 센서가 눌렸는지 기록하는
int count
변수를 만든다터치 센서의 값이 전 loop에서는 0이였지만 현재 loop에서 1로 바 뀌면 그 변수의 값을 1 증가시킨다 (count++)
( int
int height
= 180;int count
= 0;int classSize
= 30;int 변수는 -2,147,483,648과 2,147,483,647 사이의 정수값을 가지는 변수이다.
정수인 값을 저장해야 할때 int를 사용하면 된다.
즉, 아래 변수 선언은 잘못되었다.
int wrong
= 10.5;( W g x D FMCP
아래 메서드들을 사용하여 로봇을 프로그래밍 해보자.
먼저 아래 펌웨어를 추가한다
import lejos.hardware.Sound;
아래는 스피커 객채를 생성한후 소리를 내는 매소드다.
아래는 스탑와치 객채를 생성한후, 스탑와치를 시작한후, 5초동안 while 룹을 실행하는 방법이다.
Sound.setVolume(5);
//스피커 볼륨 설정Sound.beep();
//스피커 소리 내기long startFrame = System.currentTimeMillis();
//시작 시스템 시간while (System.currentTimeMillis() - startFrame < 5000) {
//프로그램 실행
}
객체 생성
( W g x MROBD MCD
셋업
결과 출력 및 리소스 정리 5초동안 실행
//object construction
EV3TouchSensor touch = new EV3TouchSensor(SensorPort.S1);
SampleProvider touchSample = touch.getMode("Touch");
float[] touchValue= new float[touch.sampleSize()];
touchSample.fetchSample(touchValue, 0);
Sound.setVolume(5);
//variable initialization and starting sequence int count = 0;
float prevTouchValue = 0;
Sound.beep();
long startFrame= System.currentTimeMillis();
//5 second loop
while (System.currentTimeMillis() - startFrame < 5000) { touchSample.fetchSample(touchValue, 0);
float curTouchValue = touchValue[0];
if (prevTouchValue== 0.0 && curTouchValue == 1.0) { count++;
System.out.println(count);
}
prevTouchValue = curTouchValue;
}
//output result Sound.beep();
System.out.println("Button pressed ");
System.out.println(count + " times.");
//wait and close resources Delay.msDelay(5000);
touch.close();
( d
1에서 100까지의 합을 콘솔에 출력하는 프로그램을 짜보자.
10,086,647의 모든 약수를 출력하는 프로그램을 짜보자.
100보다 큰 소수 10개를 콘솔에 출력하는 프로그램을 짜보자.
1000과 10000 사이의 소수들의 개수를 출력하는 프로그램을 짜보자.
x % y == 0;
//x를 y로 나누었을때 나머지를 구하는 연산자
//즉 x와 y가 서로소일때 위 문장은 참값을 가지게 된다
( d
이제는 한번 콘솔으로 지금 배운 개념들을 복습해보자.
이 단원에서 짜는 프로그램은 EV3가 아닌 컴퓨터 콘솔에서 실행되게 하자.
작성 후 Run as Java Application으로 설정하자.
( d
1에서 100까지의 합을 콘솔에 출력하는 프로그램을 짜보자.
for loop 사용
10,086,647의 모든 약수를 출력하는 프로그램을 짜보자.
for loop 1개, if문 사용하기
100보다 큰 소수 20개를 콘솔에 출력하는 프로그램을 짜보자.
for loop 2개, bool isPrime, if(isPrime) -> print
1000과 10000 사이의 소수들의 개수를 출력하는 프로그램을 짜보자.
3번 문제 응용
( d
Question 1 5050
Question 2
1, 1471, 6857, 10086647 Question 3
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197
Question 4 1061
( d
public static void main(String[] args) { System.out.println("Question 1");
int sum = 0;
for (int i = 1; i <= 100; i++) { sum += i;
}
System.out.println(sum + "");
System.out.println("Question 2");
int test = 10086647;
for (int i = 1; i <= test; i++) { if (test % i == 0) {
System.out.println(i + "");
} }
System.out.println("Question 3");
int count = 0;
for (int i = 100; count < 20; i++) { boolean isPrime = true;
for (int j = 2; j < i; j++) { if (i % j == 0) {
isPrime = false;
} }
if (isPrime) {
System.out.print(i+ ", ");
count++;
} }
System.out.println();
System.out.println("Question 4");
count = 0;
for (int i = 1000; i <= 10000; i++) { boolean isPrime = true;
for (int j = 2; j < i; j++) { if (i % j == 0) {
isPrime = false;
} }
if (isPrime) { count++;
} }
System.out.println(count +"");
System.out.println("Done");
}
3-1. 객채, 클래스, 메서드 알아보기 3-2. 강아지 클래스 만들어보기
3-3. 클래스 상속 구조
) A DB O D DC OMEO E
xcs
) MA DB r-
우리 주변에 있는 것들은 모두 ‘객채’ 라고 할수 있다.
예를 들어, EV3 라지 모터는 아래와 같은 성질들을 가진 객채이다.
모터
성질 성질 변수 종류
회전 방향 boolean
회전 속도 float
연결 포트 (A, B, C, D) TachoMotorPort
인코더 값 int
(실제 leJOS 상의 클래스 구조는 약간 다르지만 일단 넘어가도록 하자)
) MA DB r-
이런 성질들에 추가하여, 모터는 아래의 행동들을 이행할수 있다.
몇몇 행동들은 모터를 움직이고, 몇몇 행동들은 모터의 속성 / 상태를 읽은 후 알려준다
모터
행동 반환
모터 속도 정하기 void
인코더 값 리셋시키기 void
모터 특정 포지션으로 움직이기 void
인코더 값 읽기 int
모터 속도 읽기 int
(실제 모노브릭 상의 클래스 구조는 약간 다르지만 일단 넘어가도록 하자)
void: 아무것도 하지 않는다
) xcs
모터뿐만 아니라 책, 자동차, 영화등등 이 세계의 모든 것들은 ‘객채’
로 표현할수 있고, 그렇게 표현하는 방법을 ‘객채 지향’이라고 한다.
이런 개념을 프로그래밍에 적용한 것을 객채지향 프로그래밍 (Object Oriented Programming, OOP) 라고 한다.
OOP를 기반으로 설계된 언어들은 C#, Java, VB.NET, Python, PHP등 이 있다.
) s J PP
전 슬라이드에서 모터 ‘객채’를 표현하는데는 여러가지 기본 자 료형 타입을 같이 사용하였다.
그렇게 여러 자료형을 묶어서 객채를 만드는데는 클래스를 사 용한다.
옆은 매우 간략화된 Motor 클래 스이다. 이것을 통해 클래스의 여러 부분을 학습해보자.
public class Motor { boolean forward;
int speed;
TachoMotorPort port;
int encoderValue;
public Motor(TachoMotorPort port) { //constructor for Motor object this.port = port;
forward = true;
speed = 0;
encoderValue = 0;
}
public void SetSpeed(int speed) { //set motor speed
this.speed = speed;
}
public void ResetTacho() { //reset encoder value encoderValue = 0;
}
public int GetTachoCount() { //return encoder count return encoderValue;
}
public sbyte GetSpeed() {
//return current motor speed return speed;
} }
)
모터 객체에는 4가지의 속성이 있었는데, 이렇게 4가지의 변수 가 Motor 클래스 안에 선언되는 것으로 그 속성을 정의한다.
이 속성들은 필드 (field)라고 한 다.
이 4가지의 속성은 Motor 타입 의 인스턴스를 만들때 생성자를 통해 정의해준다.
public class Motor { boolean forward;
int speed;
TachoMotorPort port;
int encoderValue;
public Motor(TachoPort port) { //constructor for Motor object this.port = port;
forward = true;
speed = 0;
encoderValue = 0;
}
public void SetSpeed(sbyte speed) { //set motor speed
this.speed = speed;
}
public void ResetTacho() { //reset encoder value encoderValue = 0;
}
public int GetTachoCount() { //return encoder count return encoderValue;
}
public sbyte GetSpeed() {
//return current motor speed return speed;
} }
) n
속성을 필드로 나타낸다면, OPP에서 행 동은 메서드, 아니면 함수로 표현한다.
메서드를 정의하는법은 아래와 같다.
public 반환유형
메서드명(타입명 변수명..)
객체를 제어하기 위해 메서드는 값 (input)을 전달받을수 있으며, 그 전 달받는 변수는 매개변수 (parameter) 이라고 한다.
Ex) motorL.SetSpeed(80)은 모터 속도 값 80을 전달받은 것이다.
public class Motor { bool forward;
sbyte speed;
TachoPort port;
int encoderValue;
public Motor(TachoPort port) { //constructor for Motor object this.port = port;
forward = true;
speed = 0;
encoderValue = 0;
}
public void SetSpeed(int speed) { //set motor speed
this.speed = speed;
}
public void ResetTacho() { //reset encoder value encoderValue = 0;
}
public int GetTachoCount() { //return encoder count return encoderValue;
}
public sbyte GetSpeed() {
//return current motor speed return speed;
} }
) n (
반환유형은 타입명 아니면 void로 지정 할수 있다.
메소드가 끝나기 직전에 올바른 반환 유형의 변수를 반환 (return) 해야한 다.
반환을 할 필요가 없는 메서드들은 반 환유형에 void이라 적으면 된다.
public class Motor { bool forward;
sbyte speed;
TachoPort port;
int encoderValue;
public Motor(TachoPort port) { //constructor for Motor object this.port = port;
forward = true;
speed = 0;
encoderValue = 0;
}
public void SetSpeed(int speed) { //set motor speed
this.speed = speed;
}
public void ResetTacho() { //reset encoder value encoderValue = 0;
}
public int GetTachoCount() { //return encoder count return encoderValue;
}
public sbyte GetSpeed() {
//return current motor speed return speed;
} }
) P B SP M P B
메서드의 종류는 static 아니면 non- static 두개로 나눌수 있다.
non-static 메서드는 그 클래스의 객채 와 함께 사용되어야 한다
Ex) 지금까지 모터, 센서를 제어하는 모든 메서드는 non-static이다
static 메서드는 단일로 사용할수 있다
public static int method1()....
public int method2()....
int a = method1();
int b = motorL.method2();
int a = motorL.method1();
int b = method2();
public class Motor { bool forward;
sbyte speed;
TachoPort port;
int encoderValue;
public Motor(TachoPort port) { //constructor for Motor object this.port = port;
forward = true;
speed = 0;
encoderValue = 0;
}
public void SetSpeed(int speed) { //set motor speed
this.speed = speed;
}
public void ResetTacho() { //reset encoder value encoderValue = 0;
}
public int GetTachoCount() { //return encoder count return encoderValue;
}
public sbyte GetSpeed() {
//return current motor speed return speed;
} }
) n d
단 하나의 반삿값보다는 여러개의 반삿값들의 평균을 내어 threshold 값을 구하는것이 정확하다
함수를 작성하여 threshold 값을 구해보도록 하자.
몇개의 반삿값들을 평균낼 것인지
int count
어느 컬러센서의 반삿값을 측정할 것인지EV3ColorSensor color
함수
public static double getThresholdValue(int count, EV3ColorSensor color)
평균낸 반삿값들에서 계산한 threshold 값 double thresholdValue
) n d
옆에 순서와 같이 threshold값을 반환 하는 메서드를 작성해 라인트레이싱 코드에 대입해보도록 하자.
검정색 선 위에 컬러센서를 올려놓으라고 출력한다 (그 후 5초 기다려준다)
x개의 반삿값을 구한후 평균을 낸다
흰바닥 위에 컬러센서를 올려놓으라고 출력한다 (5초 기다려준다)
x개의 반삿값을 구한후 평균을 낸다 컬러 센서 객채 그리고 몇개의 (x) 평균값을
구할것인지 입력받는다
threshold 값을 구한후 반환한다 public static double getThresholdValue
(int count, EV3ColorSensor color) { double threshold;
//Calculate Threshold Value return threshold;
}
) n d
public static double getThresholdValue(intcount, EV3ColorSensor color) { SampleProvider colorSample= color.getRedMode();
float[] colorValue = new float[color.sampleSize()];
System.out.println("Place Sensor over Black Line");
Delay.msDelay(5000);
System.out.println("Calibrating...");
double retvalB = 0;
for(int i = 0; i < count; i++) {
colorSample.fetchSample(colorValue, 0);
retvalB = retvalB + colorValue[0];
}
retvalB = retvalB / count;
System.out.println("Place Sensor over White Floor");
Delay.msDelay(5000);
System.out.println("Calibrating...");
double retvalW = 0;
for(int i = 0; i < count; i++) {
colorSample.fetchSample(colorValue, 0);
retvalW = retvalW + colorValue[0];
}
retvalW = retvalW / count;
return (retvalW + retvalB) / 2;
}
) n d
이렇게 static 메서드를 사용해 보았다.public class LineTraceBangBang {
public static double getThresholdValue(intcount, EV3ColorSensor color) { ...
}
public static void main(String[] args) { ...
double midpoint = getThresholdValue(5, color);
while(touchValue[0] == 0) {
if (colorValue[0] > midpoint) { motorL.setSpeed (300);
motorR.setSpeed (50);
motorL.forward();
motorR.forward();
} else {
motorL.setSpeed (50);
motorR.setSpeed (300);
motorL.forward();
motorR.forward();
}
touchSample.fetchSample(touchValue, 0);
colorSample.fetchSample(colorValue, 0);
} }
public class Motor { bool forward;
int speed;
TachoMotorPort port;
int encoderValue;
public Motor(TachoMotorPort port) { //constructor for Motor object this.port = port;
forward = true;
speed = 0;
encoderValue = 0;
}
public void SetSpeed(int speed) { //set motor speed
this.speed = speed;
}
public void ResetTacho() { //reset encoder value encoderValue = 0;
}
public int GetTachoCount() { //return encoder count return encoderValue;
}
public sbyte GetSpeed() {
//return current motor speed return speed;
} }
) M P ORB MO
전에 motorL, motorR 두개의 모터 객채를 만든것은 Motor 타입의 2개의
‘인스턴스’를 만들었다고 볼수 있다.
이렇게 하나의 객채 (타입의 인스턴스)를 만드는 방법이 생성자 (constructor)의 역할이다.
메서드와 비슷하게 메개변수를 받을수 있지만 반환 유형을 적지 않 고 클래스의 이름과 생성자의 이름은 같아야한다.
EV3LargeRegulatedMotor
motorL
= new EV3LargeRegulatedMotor(MotorPort.B) EV3ColorSensorcolor
= new EV3ColorSensor(SensorPort.S3);
) ( s o d
그러면 연습으로 강아지 클래스를 만들어보자.
강아지
성질
이름 string
나이 int
성별 boolean
품종 string
행동
짖기 void
먹기 void
잔다 void
) ( s o d
Dog 클래스 안에 main 루프를 만들어 아래 프로그램을 실행하면 이 렇게 화면에 출력되게 만들어보자.
Chulsoo says woof!
Chulsoo is eating.
Chulsoo went to bed.
public class Dog {
public static void main(String[] args) {
Dog a = new Dog ("Chulsoo", "Bulldog", 4, false);
a.sound();
a.eat();
a.sleep();
Delay.msDelay(5000);
} }
메서드 (Methods) 생성자 (Constructor)
) ( s o d
아래와 비슷할 것이다.
전역변수 (Global Variable)
class Dog {
public string name, type;
public int age;
public boolean gender;//true if male, false if female
public Dog(string name, string type, int age, boolean gender) { //add dog
this.name = name;
this.type = type;
this.age = age;
this.gender = gender;
}
public void sound() {
//print out "[dog's name] says woof!"
System.out.println(name + " says woof!");
}
public void eat() {
//print out "[dog's name] is eating"
System.out.println(name + " is eating.");
}
public void sleep() {
//print out "[dog's name] went to bed"
System.out.println(name + " went to bed.");
} }
) ) s b
비슷하게, 센서들도 다음과 같은 성질을 가지며 행동을 한다.
초음파 센서
성질 연결 포트 (1, 2, 3, 4) SensorPort 읽기 모드 (cm, inch) UltraSonicMode
행동 센서값 (거리) 읽기 (숫자로) int
센서값 (거리) 읽기 (문자열으로) string
터치 센서
성질 연결 포트 (1, 2, 3, 4) SensorPort
읽기 모드 (하나밖에 없음) void
행동
센서값 (눌림 여부) 읽기 (숫자로) int 센서값 (눌림 여부) 읽기 (문자열으로) string
눌려있는지 확인하기 boolean
컬러 센서
성질 연결 포트 (1, 2, 3, 4) SensorPort 읽기 모드 (하나밖에 없음) ColorMode
행동
센서값 (색 / 반삿값) 읽기 (숫자로) int 센서값 (색 / 반삿값) 읽기 (문자열으로) string
색 읽기 Color
) ) s b
다음과 같이 모든 센서들은 다 비슷한 행동들, 성질들이 있다.
초음파 센서
성질 연결 포트 (1, 2, 3, 4) SensorPort 읽기 모드 (cm, inch) UltraSonicMode
행동 센서값 (거리) 읽기 (숫자로) int
센서값 (거리) 읽기 (문자열으로) string
터치 센서
성질 연결 포트 (1, 2, 3, 4) SensorPort
읽기 모드 (하나밖에 없음) void
행동
센서값 (눌림 여부) 읽기 (숫자로) int 센서값 (눌림 여부) 읽기 (문자열으로) string
눌려있는지 확인하기 boolean
컬러 센서
성질 연결 포트 (1, 2, 3, 4) SensorPort 읽기 모드 (하나밖에 없음) ColorMode
행동
센서값 (색 / 반삿값) 읽기 (숫자로) int 센서값 (색 / 반삿값) 읽기 (문자열으로) string
색 읽기 Color
예시 클래스 상속 구조이다. 비슷한 성질을 가진 객채들은 이렇게 변 수나 함수들을 공유할수 있다.
아래 링크를 확인해보자.
https://wikidocs.net/280
) ) s b
ISensor 인터페이스
I2CSensor 추상 클래스 AnalogSensor 추상 클래스 UartSensor 추상 클래스
HiTechnic 센서, Mindsensors 클래스 EV3 컬러, 자이로, 초음파, 적외선 센서 EV3 터치센서, 클래스
NXT 컬러, 빛, 소리, 터치센서 클래스
) ) s b
leJOS API에 들어가면 Tree 버튼을 클릭하여 전체 클래스 구조를 볼수 있다. 한번 확인해 보도록 하자.
4-1 모터 위치제어
4-2 모터 Sync하기 (정확한 거리 가는 로봇)
FOD CP
vp
j 2 BMCDO BFM
현재 모터의 위치를 알려준다.
1회전 = 360 Tick (즉 1 Tick = 1도)
인코더를 사용하여 정확한 거리를 이동할수 있다.
motor.resetTachoCount (): 인코더 값을 초기화 (void)
motor.getTachoCount (): 현재 인코더 tick 값을 읽는다 (int)
위치제어에는 이렇게 두 함수가 사용된다.