forked from s425077/PotatoPlan
updated docs
This commit is contained in:
parent
73b078ec7a
commit
e5a15185cb
@ -1,28 +1,105 @@
|
||||
# intelligent tractor environment implementation report
|
||||
# intelligent tractor route planning implementation report
|
||||
|
||||
The environment is a resizable two dimensional grid that has sprites for a farmhouse, crops and empty fields
|
||||
A* has been implemented. As of now, there are 4 types of fields wtih different costs:
|
||||
Grass - 1
|
||||
Dirt - 7
|
||||
Crops - 15
|
||||
4th type are obstacles (mountains) which are unpassable.
|
||||
|
||||
Apart from costs of each fields also cost or turning the agent has been implemented.
|
||||
Turning once costs 2
|
||||
Turning twice costs 9
|
||||
Cost of turning twice is so high to encourage the agent to try different path rather that just turning back after reaching its destination point.
|
||||
|
||||
House:
|
||||
All costs can be changed and are not final values.
|
||||
|
||||
![](https://lh4.googleusercontent.com/tEGhmLT2PAgvXG313YaVewDrUhMYgvY1PPmPpISbcW2BRz4UPfDph3-86YDHjHl4YdyCYAx4qhzB2fTlmA2Gh5nyg6oLM92Nwg-UtV3tKw3nLBe3RZvr47efqYMElmaQASTr-xMt)
|
||||
Very rarely agent will make a little bump instead of going forward.
|
||||
As of now we were not able to detect if it is a problem with A* algorithm or some other part of the program.
|
||||
|
||||
The tractor (in white) and crop (in red) on the field:
|
||||
Snippets of code:
|
||||
|
||||
![](https://lh4.googleusercontent.com/vd2n3rGPXDMLaaGBGBtjxVRftNryut-NYPstA4_CJwtRDrIVKVoAt-YrSZhcTysnk4cPXNEtssbVx02O9-DHUlV_JkY7nudSqanG7vCnMVMXQHSDnVjhDG8q98OelzNfxNXsMrbH)
|
||||
A* main loop:
|
||||
|
||||
The simulation can increase in speed or even be halted with the arrow keys, the current speed is displayed at the bottom left of the window The current environment spawns crops in randomly generated locations and the tractor tracks the location of crops and it will haul the target back to the house as well as fertilize newly planted crops.
|
||||
while (openList.GetSize() > 0)
|
||||
{
|
||||
current = openList.getMin();
|
||||
closedList.Insert(current);
|
||||
openList.removeMin();
|
||||
direction = current.getDirection();
|
||||
|
||||
As a task is complete on a tile its stage level will increase by one all the way up to 4 depending when it is fully grown and can be harvested,
|
||||
if (current.getCords() == target.getCords())
|
||||
break;
|
||||
|
||||
1. The soil will not support crops.
|
||||
|
||||
2. Soil is ready for crops to be planted.
|
||||
|
||||
3. Crops are planted and need fertilization.
|
||||
|
||||
4. Crops are ready for harvest.
|
||||
|
||||
var adjacentNodes = GetAdjacentNodes(current.getCords());
|
||||
foreach (var adjacentNode in adjacentNodes)
|
||||
{
|
||||
if (closedList.Exists(adjacentNode.getCords())) // check if adjacent node is on closed list, if it is, skip it
|
||||
continue;
|
||||
g = current.getG() + crops[(int)adjacentNode.getCords().X, (int)adjacentNode.getCords().Y].getCostOnMovement() + CalculateRotationCost(direction, adjacentNode.getDirection()); // calculate g - cost from start point
|
||||
if (!(openList.Exists(adjacentNode.getCords()))) // if adjacent node is not on open list, add it
|
||||
{
|
||||
|
||||
After the crops have been harvested they will return to stage 2.
|
||||
adjacentNode.setG(g);
|
||||
adjacentNode.setH(ComputeHScore(adjacentNode.getCords(), target.getCords()));
|
||||
adjacentNode.calculateF();
|
||||
adjacentNode.setParent(current);
|
||||
openList.Insert(adjacentNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g + adjacentNode.getH() < adjacentNode.getF()) // check if adjacent node is a better path than the current one
|
||||
{
|
||||
adjacentNode.setG(g);
|
||||
adjacentNode.calculateF();
|
||||
adjacentNode.setParent(current);
|
||||
}
|
||||
}
|
||||
|
||||
A short video of how the project works:[video](https://uam-my.sharepoint.com/:v:/g/personal/domhof1_st_amu_edu_pl/Ec1ThqI2DSZNob2-6IrfPvYBe9_G2xfK8Ffn04dSklsWIQ?e=OrTqmy)
|
||||
}
|
||||
}
|
||||
|
||||
// backtrack to create path
|
||||
while (current != null)
|
||||
{
|
||||
path.AddNode(current);
|
||||
current = current.getParent();
|
||||
}
|
||||
|
||||
|
||||
Successor function:
|
||||
|
||||
private List<Nodes> GetAdjacentNodes(Vector2 currentPos)
|
||||
{
|
||||
var adjacentNodes = new List<Nodes>()
|
||||
|
||||
{
|
||||
new Nodes(new Vector2(currentPos.X, currentPos.Y+1), 0),
|
||||
new Nodes(new Vector2(currentPos.X + 1, currentPos.Y), 1),
|
||||
new Nodes(new Vector2(currentPos.X, currentPos.Y - 1), 2),
|
||||
new Nodes(new Vector2(currentPos.X - 1, currentPos.Y), -1),
|
||||
};
|
||||
|
||||
//check if out of range
|
||||
for (int i = 3; i >= 0; i--)
|
||||
{
|
||||
if (adjacentNodes[i].getCords().X < 0 || adjacentNodes[i].getCords().Y < 0)
|
||||
adjacentNodes.Remove(adjacentNodes[i]);
|
||||
else
|
||||
{
|
||||
if (adjacentNodes[i].getCords().X > Size.X - 1 || adjacentNodes[i].getCords().Y > Size.Y - 1)
|
||||
adjacentNodes.Remove(adjacentNodes[i]);
|
||||
}
|
||||
}
|
||||
// return if not an obstacle
|
||||
return adjacentNodes.Where(
|
||||
item => crops[(int)item.getCords().X, (int)item.getCords().Y].Status != 0).ToList();
|
||||
}
|
||||
|
||||
|
||||
Heuristic function:
|
||||
|
||||
// Heuristic function, Manhattan method.
|
||||
public int ComputeHScore(Vector2 currentNode, Vector2 endNote)
|
||||
{
|
||||
return (int)(Math.Abs(endNote.X - currentNode.X) + Math.Abs(endNote.Y - currentNode.Y));
|
||||
}
|
Loading…
Reference in New Issue
Block a user