오늘은 (1) vehicle의 미래의 위치와 도로의 중앙선 사이의 거리와 (2) 도로의 폭 사이의 관계성을 관찰하여, vehicle이 도로 폭 안에서 움직이도록 하는 작업부터 시작해 보겠습니다~^^*
어제의 핵심코드에서 연결하여 공부할 것이라, 아래 동영상 강의를 처음부터 다시 또 보셔도 좋을 것 같습니다! 복습! 바람직하지 말입니다!! 오늘 이 동영상 강의를 끝내게 되네요!! 와우!!
vehicle의 미래의 위치와 도로의 중앙선 사이의 거리가 도로의 반지름보다 크면?
네~^^* vehicle이 미래 시점에 도로 폭 밖으로 벗어나게 되는 것이 예상되네요!
그러면, 문제 해결법은?
그렇죠~~^^*
도로의 중앙선을 목표로 몸을 돌리면 되겠네요?
vehicle의 미래의 위치에서 도로 중앙선 위로 수직으로 내려간 지점을 목표로, 지금 바로 몸을 돌리면, 미래 시점에 도로 폭 안에 들어가 있을 수 있겠지요?
바로 그 지점이?
그렇죠~~^^*
Scalar Projection! 그리고 어제 우리는 이 지점을 몸을 틀어 향할 목표! target이라고 부르기로 했었어요~~
vehicle의 미래 위치와 도로의 중앙선 사이의 거리가 도로의 반지름보다 작으면?
미래 시점에도 vehicle이 도로 폭 안에 들어와 있는 것이니까~ 편안히 쉬면 되어요~~^^*
그러면 이 과정을 코드로 작성해 볼게요~~^^*
let d = p5.Vector.dist(future, target);
if (d > path.radius) {
return this.seek(target);
} else {
return createVector(0, 0);
}
target 위치로 다가가는 함수 seek()입니다~^^*
seek(target) {
let force = p5.Vector.sub(target, this.pos);
let desiredSpeed = this.maxSpeed;
force.setMag(desiredSpeed);
force.sub(this.vel);
force.limit(this.maxForce);
return force;
}
음 근데요…. 일정이 있는 곳 근처 까페에서 아침 일찍부터 작업을 했는데…오늘 왠일인지 저의 컴퓨터가 와이파이를 잘 받지 못하네요….
오후에 와이파이 잘 받을 수 있는 곳에서 다시 돌아올게요!
오늘도 멋진 아침! 보내시구요! 우리는 오후에 다시 만나요~~~^^*
네~~^^* 와이파이를 제 컴퓨터가 잘 수용하는 곳으로 왔습니다~^^* 점심 맛있게 드셨어요~~^^*?
이제 상호작용 요소를 준비해 보기로 하겠습니다~^^*
마우스/손끝으로 화면 속 도로의 끝 위치를 조정해 보도록 할게요~^^* 그러면 path following이 좀더 재미있어지겠지요~~^^*
path.end.y = mouseY;
도로 폭 안에서 움직이고, 도로는 우리의 손끝을 따라 기울기를 달리하고~^^*
재미있는 path follwing 전체 코드를 저와 함께 살펴 볼까요~~^^*
알고리즘과 핵심코드에 대해 자세히 살펴보았으니, 전체 코드 안에 주석을 넣지 않도록 할게요~~^^*
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="path.js"></script>
<script src="vehicle.js"></script>
<script src="sketch.js"></script>
</body>
</html>
class Path {
constructor(x1, y1, x2, y2) {
this.start = createVector(x1, y1);
this.end = createVector(x2, y2);
this.radius = 20;
}
show() {
stroke(255);
strokeWeight(2);
line(this.start.x, this.start.y, this.end.x, this.end.y);
stroke(255, 100);
strokeWeight(this.radius * 2);
line(this.start.x, this.start.y, this.end.x, this.end.y);
}
}
function findProjection(pos, a, b) {
let v1 = p5.Vector.sub(a, pos);
let v2 = p5.Vector.sub(b, pos);
v2.normalize();
let sp = v1.dot(v2);
v2.mult(sp);
v2.add(pos);
return v2;
}
class Vehicle {
constructor(x, y) {
this.pos = createVector(x, y);
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxSpeed = 6;
this.maxForce = 0.1;
this.r = 16;
}
follow(path) {
let future = this.vel.copy();
future.mult(20);
future.add(this.pos);
fill(255, 0, 0);
noStroke();
circle(future.x, future.y, 16);
let target = findProjection(path.start, future, path.end);
fill(0, 255, 0);
noStroke();
circle(target.x, target.y, 16);
let d = p5.Vector.dist(future, target);
if (d > path.radius) {
return this.seek(target);
} else {
return createVector(0, 0);
}
}
seek(target) {
let force = p5.Vector.sub(target, this.pos);
let desiredSpeed = this.maxSpeed;
force.setMag(desiredSpeed);
force.sub(this.vel);
force.limit(this.maxForce);
return force;
}
applyForce(force) {
this.acc.add(force);
}
update() {
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.set(0, 0);
}
show() {
stroke(255);
strokeWeight(2);
fill(255);
push();
translate(this.pos.x, this.pos.y);
rotate(this.vel.heading());
triangle(-this.r, -this.r / 2, -this.r, this.r / 2, this.r, 0);
pop();
}
edges() {
if (this.pos.x > width + this.r) {
this.pos.x = -this.r;
} else if (this.pos.x < -this.r) {
this.pos.x = width + this.r;
}
if (this.pos.y > height + this.r) {
this.pos.y = -this.r;
} else if (this.pos.y < -this.r) {
this.pos.y = height + this.r;
}
}
}
let vehicle;
let path;
function setup() {
createCanvas(400, 400);
vehicle = new Vehicle(100, 100);
vehicle.vel.x = 2;
path = new Path(0, height / 2, width, height / 2);
}
function draw() {
background(0);
path.end.y = mouseY;
let force = vehicle.follow(path);
vehicle.applyForce(force);
vehicle.edges();
vehicle.update();
vehicle.show();
path.show();
}
자 그럼 이제! 드디어!
마우스/손가락을 움직여 도로의 각도를 조정하면서 vehicle이 도로 폭 안에 잘 들어오는지 관찰해 볼까요~~^^*
Path를 잘 Follow 하다보니, 어머나! Path Following 프로그램을 완성하였네요!!!
오늘도 저와 함꼐 작은 성공을 완성해 주셔서 감사합니다~~^^*
네! 마스터께서 여기서 안주하지 말고 여정을 계속 이어가라고 하시네요!
네! 다음 도전을 우리 함께 내일 맞이해 볼까요!
혹여 다음 도전이 좀 큰 산이라 오르는데 숨이 차오르게 된다고 해도!
우리 이 노래를 함께 들으며 또 다른 작은 성공을 만들어 내 볼까요~?
오늘 하루도 수고 많으셨어요~~^^* 편안한 저녁 보내시구요~^^*
우리 내일 아침 일찍 만나서 코딩 공부 함께 하는 거에요~~^^*
넵!!!! 꿈은 이루어 집니다~~!!!!
댓글 남기기