Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aco vision to movement #183

Merged
merged 23 commits into from
Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9bb43f5
"Cardinal point detection through view. Need to have knowledge of ord…
Travisd13 Feb 22, 2022
1be6875
"TODO update to jog memory"
Travisd13 Feb 22, 2022
d317076
"Angle patch so runs from 0 degrees - 360 degrees allowing cardinal p…
Travisd13 Feb 23, 2022
3465f21
"Angle patch remove comment"
Travisd13 Feb 23, 2022
fba5b6a
"Binary cardinal search succesfully tested and alered"
Travisd13 Feb 23, 2022
84a594a
"Determining possible movements based off agents vision"
Travisd13 Feb 23, 2022
976d3c7
"Determine avaliable movements"
Travisd13 Feb 23, 2022
1b8122b
"Agent's ability to access surrounding pheramones - Needs testing"
Travisd13 Feb 23, 2022
fde508e
"Movements and pheromone retrieval testing complete."
Travisd13 Feb 23, 2022
d532e81
"Agent movement with obstacle detection completed"
Travisd13 Feb 23, 2022
800334b
"Unused import removal"
Travisd13 Feb 23, 2022
ff2a2c4
"Unused parameter removal"
Travisd13 Feb 23, 2022
452ccdd
"Aco agent conversation resolution"
Travisd13 Feb 23, 2022
f7e212b
"AcoGrid display conversation resolution"
Travisd13 Feb 23, 2022
206e782
"Finish agent movement within grid"
Travisd13 Feb 23, 2022
5bcd19a
"Basic agent movement completed and tested"
Travisd13 Feb 23, 2022
42d0ed7
"Max pheromone value will need to be testes within our environments"
Travisd13 Feb 23, 2022
77c4ee5
"Starting to work - Agent seems to be getting stuck"
Travisd13 Feb 23, 2022
609112c
"Passing tests and bug update"
Travisd13 Feb 24, 2022
9abf328
"All tests passing again after bug fix"
Travisd13 Feb 24, 2022
5af7ab9
"Ray angle rounding to allow core always correct cardinal point detec…
Travisd13 Feb 24, 2022
59c746c
"Vector 360 == 0 edge case fixed and test created"
Travisd13 Feb 24, 2022
be82de6
"Testing update and small bug fixes"
Travisd13 Mar 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/app/controller/GameEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public GameEngine(Map map, Renderer renderer)

public void tick()
{
map.getAgents().forEach(a -> a.updateView(graphicsEngine.compute(map, a)));

for (Agent a :map.getAgents())
{
Vector startPoint = a.getPosition();
Expand All @@ -40,8 +42,6 @@ public void tick()
a.updateLocation(endPoint);
}

map.getAgents().forEach(a -> a.updateView(graphicsEngine.compute(map, a)));

renderer.render();
}

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/app/controller/graphicsEngine/Ray.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public Vector getU()
return u;
}

public double getAngle()
{
return angle;
}

public double angle()
{
return v.sub(u).getAngle();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/app/controller/graphicsEngine/RayTracing.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ private ArrayList<Ray> scatterRays(Agent agent)
{
ArrayList<Ray> rays = new ArrayList<>();
Vector origin = agent.getPosition();
Vector direction = agent.getDirection();
Ray ray = new Ray(origin, direction);
Vector nextPosition = origin.add(agent.getDirection());
Ray ray = new Ray(origin, nextPosition);
double theta = 0;
for(int i = 0; i < noOfRays; i++)
{
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/app/controller/linAlg/Vector.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@ public Vector rotate(double degrees)
public double getAngle()
{
// + 90 to set the angle to north, negate angle to make it clockwise
return (-Math.toDegrees(Math.atan2(y,x)) + 360.0 + 90.0) % 360.0;
// Rounded to 1 decimal place
double angle = (-Math.toDegrees(Math.atan2(y,x)) + 360.0 + 90.0) % 360.0;
double roundedAngle = (double) Math.round(angle * 10) / 10;

if(roundedAngle == 360.0)
{
roundedAngle = 0.0;
}
return roundedAngle;
}

public Vector copy()
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/app/model/Grid/AcoGrid.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.model.Grid;

import app.model.agents.ACO.AcoAgent;
import app.model.agents.Cells.Cell;
import app.model.agents.Cells.CellType;
import app.model.agents.Cells.PheromoneCell;

Expand All @@ -25,7 +26,7 @@ public void updateAgent(AcoAgent agent)
int col = getCellCol(agent.getPosition());

PheromoneCell cell = (PheromoneCell) super.getCellAt(row, col);
cell.updatePheromone(agent.releaseMaxPheramone());
cell.updatePheromone(agent.releaseMaxPheromone());
}

public void evaporationProcess()
Expand All @@ -40,13 +41,14 @@ public void evaporationProcess()
}
}

public void displayGridState()
//TODO Rewrite method to toString
public void print()
{
for(int i = 0; i < getRowDimension(); i++)
for(Cell[] line : grid)
{
for(int j = 0; j < getColDimension(); j++)
for(Cell cell: line)
{
System.out.print(grid[i][j].toString() + " ");
System.out.print(cell.toString() + " ");
}
System.out.println();
}
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/app/model/Grid/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public class Grid

public Grid(double length, double width, CellType type)
{
rowSize = (int)(length / cellSize);
colSize = (int)(width / cellSize);
//Addition of single cell to accomodate for 0 cells
rowSize = (int)(Math.ceil(length / cellSize) + 1);
colSize = (int)(Math.ceil(width / cellSize) + 1);
this.type = type;

grid = initializeAllCells();
Expand Down Expand Up @@ -67,4 +68,9 @@ public int getColDimension()
{
return grid[0].length;
}

public double getCellSize()
{
return cellSize;
}
}
23 changes: 7 additions & 16 deletions src/main/java/app/model/Map.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import app.controller.linAlg.Vector;
import app.controller.settings.Settings;
import app.controller.settings.SettingsObject;
import app.model.agents.ACO.AcoAgent;
import app.model.agents.Agent;
import app.model.agents.Human;
import app.model.agents.WallFollowAgent;
Expand Down Expand Up @@ -38,14 +39,12 @@ public Map(Settings settings)

agents = new ArrayList<>();

/* Adds temporary WallFollowAgent */
Vector srt = new Vector(randX(intruderSpawn), randY(intruderSpawn));
Vector dir = new Vector(1,0);
WallFollowAgent wallAgent = new WallFollowAgent(srt, dir, 10);
//Assumes the wallFollowAgent is a guard
wallAgent.setMaxWalk(settings.getWalkSpeedGuard());
wallAgent.setMaxSprint(settings.getSprintSpeedGuard());
agents.add(wallAgent);
/* Adds temporary AcoAgent */
Vector srt = new Vector(14, 12);
Vector dir = new Vector(0,1);
AcoAgent.initializeWorld(settings.getWidth(), settings.getHeight());
AcoAgent agent = new AcoAgent(srt, dir, 10);
agents.add(agent);

// On creation add the right number of guards
for(int i = 0; i < settings.getNoOfGuards(); i++)
Expand All @@ -60,14 +59,6 @@ public Map(Settings settings)
Vector intruderStart = new Vector(randX(intruderSpawn), randY(intruderSpawn));
/* TODO intruder agents here!!! */
}

Vector humanStart = new Vector(randX(guardSpawn), randY(guardSpawn));
human = new Human(humanStart, new Vector(1,0), 10);
//Assumes the human is a guard
human.setMaxWalk(settings.getWalkSpeedGuard());
human.setMaxSprint(settings.getSprintSpeedGuard());
agents.add(human);

System.out.println("done.");
}

Expand Down
168 changes: 163 additions & 5 deletions src/main/java/app/model/agents/ACO/AcoAgent.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,188 @@
package app.model.agents.ACO;

import app.controller.graphicsEngine.Ray;
import app.controller.linAlg.Vector;
import app.model.Grid.AcoGrid;
import app.model.agents.AgentImp;
import app.model.agents.Cells.PheromoneCell;
import app.model.map.Move;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

//TODO Accomodate for agents clashes
public class AcoAgent extends AgentImp
{
//TODO Place actual max pheramone value
private double maxPheramone = 10;
private double maxPheromone = 1;
private static AcoGrid world;
private double cellSize = world.getCellSize();
Random randomGenerator = new Random(1);

private HashMap<Integer, PheromoneCell> agentMap = new HashMap<>();

private int[] cardinalAngles = {0, 90, 180, 270};
private double epsilon = 0.3;

public AcoAgent(Vector position, Vector direction, double radius)
{
super(position, direction, radius);
world.updateAgent(this);
}

// 1. Agent looks around
// 2. Determine cardinal rays
// 3. Determine positions to move to that aren't blocked (Wall or agent)
// 4. Determine pheromone value at each position
// 5. Determine best move and execute it.
// 6. After all agents have gone, perform evaporation procedure
@Override
public Move move()
{
Ray[] cardinalRays = detectCardinalRays();
ArrayList<Vector> possibleMovements = determineAvailableMovements(cardinalRays);
ArrayList<Double> cellPheromones = accessAvaliableCellPheromones(possibleMovements);

ArrayList<Vector> equivalentMinMoves = determineEquivalentMinMoves(cellPheromones, possibleMovements);
Vector moveVector= selectRandomEquivalentMove(equivalentMinMoves);
return new Move(position, moveVector);
}

@Override
public void updateLocation(Vector endPoint)
{
position = endPoint;
world.updateAgent(this);
System.out.println(position.toString());
}

//TODO Implement movement bias based on target direction
public ArrayList<Vector> determineEquivalentMinMoves(ArrayList<Double> cellPheromones, ArrayList<Vector> possibleMovements)
{
double minValue = Double.MAX_VALUE;
ArrayList<Vector> equivalentMoves = new ArrayList<>();

for(int i = 0; i < cellPheromones.size(); i++)
{
if(cellPheromones.get(i) == minValue)
{
equivalentMoves.add(possibleMovements.get(i));
}
else if(cellPheromones.get(i) < minValue)
{
equivalentMoves.clear();
minValue = cellPheromones.get(i);
equivalentMoves.add(possibleMovements.get(i));
}
}
return equivalentMoves;
}

public Vector selectRandomEquivalentMove(ArrayList<Vector> equivalentMoves)
{
return equivalentMoves.get(randomGenerator.nextInt(equivalentMoves.size()));
}

public ArrayList<Double> accessAvaliableCellPheromones(ArrayList<Vector> possibleMovements)
{

ArrayList<Double> cellPheromoneValues = new ArrayList<>();

for(Vector movement : possibleMovements)
{
Vector resultingPosition = position.add(movement);
PheromoneCell possibleCell = (PheromoneCell) world.getCellAt(resultingPosition);
cellPheromoneValues.add(possibleCell.currentPheromoneValue());
}
return cellPheromoneValues;
}

public ArrayList<Vector> determineAvailableMovements(Ray[] cardinalRays)
{
ArrayList<Vector> possibleMovements = new ArrayList<>();

for(int i = 0; i < cardinalRays.length; i++)
{
if(cardinalRays[i].rayLength() > cellSize + epsilon)
{
possibleMovements.add(angleToGridMovementLink(cardinalAngles[i]));
}
}
return possibleMovements;
}

public Vector angleToGridMovementLink(int angle)
{
switch(angle)
{
case 0:
return new Vector(0, cellSize);
case 90:
return new Vector(cellSize, 0);
case 180:
return new Vector(0, -cellSize);
case 270:
return new Vector(-cellSize, 0);
default:
return null;
}
}

public Ray[] detectCardinalRays()
{
Ray[] cardinalRays = new Ray[cardinalAngles.length];

for(int i = 0; i < cardinalAngles.length; i++)
{
cardinalRays[i] = detectCardinalPoint(cardinalAngles[i]);
}
return cardinalRays;
}

public Ray detectCardinalPoint(double targetCardinalAngle)
{
int upperBound = view.size() - 1;
int lowerBound = 0;

while(lowerBound <= upperBound)
{
int midPoint = calculateMidPoint(upperBound, lowerBound);
double currentAngle = view.get(midPoint).angle();

if(approximateAngleRange(currentAngle, targetCardinalAngle))
{
return view.get(midPoint);
}
else if(currentAngle < targetCardinalAngle)
{
lowerBound = midPoint + 1;
}
else if(currentAngle > targetCardinalAngle)
{
upperBound = midPoint - 1;
}
}
System.out.println("Cardinal Point not found");
return null;
}

public int calculateMidPoint(int upperBound, int lowerBound)
{
return lowerBound + (upperBound - lowerBound)/2;
}

public double releaseMaxPheramone()
public boolean approximateAngleRange(double detectedAngle, double targetAngle)
{
return maxPheramone;
if(detectedAngle < (targetAngle + epsilon) && detectedAngle > (targetAngle - epsilon))
{
return true;
}
return false;
}

public double releaseMaxPheromone()
{
return maxPheromone;
}

public static void initializeWorld(double width, double height)
Expand All @@ -40,4 +193,9 @@ public static AcoGrid accessWorld()
{
return world;
}
}

public int[] getCardinalAngles()
{
return cardinalAngles;
}
}
Loading