135 lines
4.1 KiB
TypeScript
135 lines
4.1 KiB
TypeScript
![]() |
// SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
// Author: Sascha Nitsch https://contentnation.net/@grumpydevelop
|
||
|
|
||
|
import { RobotStatus } from './robotstatus';
|
||
|
import { RoboBase } from './robobase';
|
||
|
|
||
|
class Rabbit extends RoboBase {
|
||
|
carrotX: number = 0;
|
||
|
carrotY: number = 0;
|
||
|
running = false;
|
||
|
mode = 'MUNCH';
|
||
|
munchtime = 0;
|
||
|
ready() {
|
||
|
console.log('rabbit is ready');
|
||
|
}
|
||
|
|
||
|
start() {
|
||
|
console.log('simulation started');
|
||
|
this.cmd.powerRight = 0;
|
||
|
this.cmd.powerLeft = 0;
|
||
|
this.cmd.radarMin = 270;
|
||
|
this.cmd.radarMax = 90;
|
||
|
this.sendCmd();
|
||
|
this.running = true;
|
||
|
}
|
||
|
|
||
|
statusReady(status: RobotStatus) {
|
||
|
if (!this.running) {
|
||
|
return;
|
||
|
}
|
||
|
switch (this.mode) {
|
||
|
case 'RUN':
|
||
|
const dx = this.carrotX - status.posX;
|
||
|
const dy = this.carrotY - status.posY;
|
||
|
const dir = Math.atan2(dx, -dy) * 180 / Math.PI;
|
||
|
const dst = Math.sqrt(dx * dx + dy * dy);
|
||
|
let rot = dir - status.orientation;
|
||
|
if (rot < -180) {
|
||
|
rot += 360;
|
||
|
}
|
||
|
if (rot > 180) {
|
||
|
rot -= 360;
|
||
|
}
|
||
|
rot = Math.min(Math.max(-90, rot), 90);
|
||
|
let desiredSpeed = 1;
|
||
|
if (dst < 30) {
|
||
|
desiredSpeed = dst / 40;
|
||
|
}
|
||
|
const speedDiff = Math.sin(rot * Math.PI / 180.0);
|
||
|
// desired speed of left chain
|
||
|
let dsl = desiredSpeed + speedDiff;
|
||
|
// desired speed of right chain
|
||
|
let dsr = desiredSpeed - speedDiff;
|
||
|
// prevent overflows, reduce to limits but keep relative difference if possible
|
||
|
if (dsl > 1) {
|
||
|
dsr -= Math.max(dsl - 1, -1);
|
||
|
dsl = 1;
|
||
|
} else if (dsr > 1) {
|
||
|
dsl -= Math.max(dsr - 1, -1);
|
||
|
dsr = 1;
|
||
|
}
|
||
|
this.cmd.powerLeft = dsl;
|
||
|
this.cmd.powerRight = dsr;
|
||
|
// close and slow enough?
|
||
|
if (dst < 5 && Math.abs(status.chainSpeedLeft) < .1 && Math.abs(status.chainSpeedRight) < .1) {
|
||
|
this.mode = 'MUNCH';
|
||
|
this.cmd.powerLeft = 0;
|
||
|
this.cmd.powerRight = 0;
|
||
|
this.munchtime = 5 * 20; // 5 sec
|
||
|
console.log("munch");
|
||
|
}
|
||
|
break;
|
||
|
case "MUNCH":
|
||
|
if (this.munchtime) {
|
||
|
--this.munchtime;
|
||
|
} else {
|
||
|
this.mode = 'RUN';
|
||
|
this.carrotX = Math.random() * (this.width - 20) + 10;
|
||
|
this.carrotY = Math.random() * (this.height - 20) + 10;
|
||
|
console.log("target reached, new target", this.carrotX, this.carrotY);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
if (status.contactPoints && status.contactPoints.length > 0) {
|
||
|
status.contactPoints.forEach((cp) => {
|
||
|
// adjust angle by radar rotation
|
||
|
const angle = cp.angle + status.radarPos;
|
||
|
// global angle from position
|
||
|
const globalAngle = angle + status.orientation;
|
||
|
const targetX = Math.sin(globalAngle * Math.PI / 180)* cp.dist + status.posX;
|
||
|
const targetY = -Math.cos(globalAngle * Math.PI / 180)* cp.dist + status.posY;
|
||
|
// run the other way +- 45 degree
|
||
|
let newTargetAngle = globalAngle + 180 + Math.random()*90 - 45
|
||
|
if (newTargetAngle >= 360) {
|
||
|
newTargetAngle -= 360;
|
||
|
}
|
||
|
if (newTargetAngle < 0) {
|
||
|
newTargetAngle += 360;
|
||
|
}
|
||
|
// target is 50-100 units away
|
||
|
const newTargetDistance = Math.random() * 50 + 50;
|
||
|
this.carrotX = status.posX + Math.sin(newTargetAngle * Math.PI / 180) * newTargetDistance;
|
||
|
this.carrotY = status.posY - Math.cos(newTargetAngle * Math.PI / 180) * newTargetDistance;
|
||
|
if (this.carrotX > this.width - 10) {
|
||
|
this.carrotX = this.width - 10;
|
||
|
}
|
||
|
if (this.carrotY > this.height - 10) {
|
||
|
this.carrotY = this.height - 10;
|
||
|
}
|
||
|
if (this.carrotX < 0) {
|
||
|
this.carrotX = 10;
|
||
|
}
|
||
|
if (this.carrotY < 0) {
|
||
|
this.carrotY = 10;
|
||
|
}
|
||
|
console.log("enemy at", targetX, targetY, "run to", this.carrotX, this.carrotY);
|
||
|
});
|
||
|
}
|
||
|
this.sendCmd();
|
||
|
}
|
||
|
|
||
|
lost() {
|
||
|
console.log('we lost');
|
||
|
this.disconnect();
|
||
|
}
|
||
|
|
||
|
won() {
|
||
|
console.log('we won');
|
||
|
this.disconnect();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var rabbit = new Rabbit('rabbit', 'scout');
|
||
|
rabbit.connect();
|