xxxxxxxxxx
249
// Variáveis do ambiente
const environmentSize = 400;
const robotSize = 32;
const obstacleSize = 32;
const explorationRate = 0.1;
const episodeDuration = 10;
// Variáveis da rede neural
const inputSize = 14; // Número de entradas da rede neural
const outputSize = 2; // Número de saídas da rede neural
let robot;
let obstacles = [];
let target;
let episode = 0;
let startTime;
// Criação do modelo da rede neural
const neuralNetwork = tf.sequential();
neuralNetwork.add(tf.layers.dense({ units: 32, inputShape: [inputSize], activation: 'relu' }));
neuralNetwork.add(tf.layers.dense({ units: outputSize, activation: 'tanh' }));
neuralNetwork.compile({ optimizer: 'adam', loss: 'meanSquaredError' });
function setup() {
createCanvas(environmentSize, environmentSize);
init();
}
function init(){
startTime = millis(); // Obtém o tempo inicial em milissegundos
robot = new Robot(random(environmentSize), random(environmentSize));
target = createVector(random(environmentSize), random(environmentSize));
obstacles = []
// Criação dos obstáculos
for (let i = 0; i < 5; i++) {
let x = random(obstacleSize, environmentSize - obstacleSize);
let y = random(obstacleSize, environmentSize - obstacleSize);
obstacles.push(new Obstacle(x, y));
}
episodeScore = 0;
startTime = millis();
}
function draw() {
background(220);
// Atualização e renderização dos robôs
let inputs = getInputs(robot); // Obtém as entradas da rede neural
let outputs = getOutputs(inputs); // Usa a rede neural para obter as saídas
let velocity = createVector(outputs[0], outputs[1]); // Saída representa a velocidade do robô
robot.update(velocity);
// Renderiza o robô
robot.render();
// Renderização dos obstáculos
for (let i = 0; i < obstacles.length; i++) {
let obstacle = obstacles[i];
obstacle.render();
}
fill(255, 0, 0);
circle(target.x, target.y, 10);
train();
}
let isTraining = false; // Variable to control if training is in progress
function train() {
if (isTraining) {
return Promise.resolve(); // Return a resolved promise if training is already in progress
}
isTraining = true; // Set the training flag to true
const numEpisodes = 1000; // Number of training episodes
const maxSteps = 100; // Maximum number of steps per episode
let episodeScore = 0;
// Reset robot's position
robot.position = createVector(random(environmentSize), random(environmentSize));
return new Promise((resolve) => {
for (let step = 0; step < maxSteps; step++) {
let inputs = getInputs(robot);
let outputs = getOutputs(inputs);
// Apply exploration rate (epsilon-greedy)
if (Math.random() < explorationRate) {
outputs[0] = random(-1, 1);
outputs[1] = random(-1, 1);
}
let velocity = createVector(outputs[0], outputs[1]);
robot.update(velocity);
episodeScore += robot.score;
let elapsedTime = (millis() - startTime) / 1000;
// Check if the robot reached the target
if (dist(robot, target) < 30) {
// Positive reward for reaching the target
episodeScore += 10;
endEpisode();
break; // Exit the step loop
}
if (elapsedTime >= episodeDuration) {
episodeScore -= 1;
endEpisode();
break; // Exit the step loop
}
}
// Perform neural network training using the episode score
let inputsTensor = tf.tensor2d([getInputs(robot)]);
let scoreTensor = tf.tensor2d([[episodeScore, 0]]);
return neuralNetwork.fit(inputsTensor, scoreTensor, { epochs: 1 }).then(() => {
// Print the episode score
console.log(`Episode ${episode + 1} - Score: ${episodeScore}`);
isTraining = false; // Set the training flag to false
init();
resolve(); // Resolve the promise to indicate training completion
episode++;
});
});
}
function endEpisode() {
// Reinicia a pontuação do robô
robot.score = 0;
init();
}
// Classe do Robô
class Robot {
constructor(x, y) {
this.position = createVector(x, y);
this.previousPosition = createVector(x, y);
this.score = 0;
}
update(velocity) {
// Atualiza a posição do robô com base na velocidade
this.position.add(velocity);
robot.checkBoundaryCollision();
}
render() {
// Renderiza o robô
fill(255, 0, 0);
rectMode(CENTER);
rect(this.position.x, this.position.y, robotSize, robotSize);
}
collidesWith(object) {
// Verifica se o robô colide com outro objeto (robô ou obstáculo)
let distance = this.position.dist(object.position);
let collisionDistance = robotSize * sqrt(1.5);
return distance <= collisionDistance;
}
checkBoundaryCollision() {
// Verifica se o robô colide com as paredes
if (this.position.x < robotSize / 2 || this.position.x > environmentSize - robotSize / 2) {
this.score -= 0.1;
this.position.x = constrain(this.position.x, robotSize / 2, environmentSize - robotSize / 2);
}
if (this.position.y < robotSize / 2 || this.position.y > environmentSize - robotSize / 2) {
this.score -= 0.1;
this.position.y = constrain(this.position.y, robotSize / 2, environmentSize - robotSize / 2);
}
// Verifica colisões com os obstáculos
for (let i = 0; i < obstacles.length; i++) {
let obstacle = obstacles[i];
if (this.collidesWith(obstacle)) {
this.score -= 1;
// Ajusta a posição para evitar sobreposição com o obstáculo
this.position.x = this.previousPosition.x;
this.position.y = this.previousPosition.y;
}
}
this.previousPosition.x = this.position.x;
this.previousPosition.y = this.position.y;
}
}
// Classe do Obstáculo
class Obstacle {
constructor(x, y) {
this.position = createVector(x, y);
this.size = obstacleSize;
}
render() {
// Renderiza o obstáculo
fill(0, 0, 255);
rectMode(CENTER);
rect(this.position.x, this.position.y, obstacleSize, obstacleSize);
}
}
// Função para obter as entradas da rede neural
function getInputs(robot) {
let inputs = [];
// Adicione as coordenadas do robô como entradas
inputs.push(robot.position.x);
inputs.push(robot.position.y);
// Adicione as coordenadas dos obstáculos como entradas
for (let i = 0; i < obstacles.length; i++) {
let obstacle = obstacles[i];
inputs.push(obstacle.position.x);
inputs.push(obstacle.position.y);
}
inputs.push(target.x);
inputs.push(target.y);
return inputs;
}
function normalizeOutput(value, min, max) {
return ((value + 1) / 2) * (max - min) + min;
}
// Função para obter as saídas da rede neural com base nas entradas
function getOutputs(inputs) {
const inputTensor = tf.tensor2d([inputs]);
const outputTensor = neuralNetwork.predict(inputTensor);
const outputData = outputTensor.dataSync();
const normalizedOutputs = outputData.map(value => normalizeOutput(value, -10, 10));
return normalizedOutputs;
}