navigation updated with completed dijkstra's algo
Dependents: R5 2016 Robotics Team 1
Diff: navigation.cpp
- Revision:
- 0:fd72f6df078c
- Child:
- 1:a53d97b74fab
diff -r 000000000000 -r fd72f6df078c navigation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/navigation.cpp Fri Oct 30 15:48:48 2015 +0000 @@ -0,0 +1,183 @@ +#include "navigation.h" +#include "stdint.h" +#include <iostream> +#include <fstream> +#include <stack> +#include <set> + +// FUNCTION: +// Navigation(int size = DEFAULT_SIZE) +// IN-PARAMETERS: +// Number of initial vertices (DEFAULT = 1) +// OUT-PARAMETERS: +// None +// DESCRIPTION: +// Default and 1-parameter constructor. +Navigation::Navigation(int size = DEFAULT_SIZE) : vertex(DEFAULT_VERTEX), + angle(DEFAULT_ANGLE) +{ + graph.resize(size); +} + +// FUNCTION: +// addGraphNode(uint16_t src, uint16_t target, uint16_t dist, +// uint16_t angle) +// IN-PARAMETERS: +// Source node (uint16_t), target node (uint16_t), edge distance +// (uint16_t), and angle (uint16_t) +// OUT-PARAMETERS: +// None +// DESCRIPTION: +// Adds a graph node to the graph. +void Navigation::addGraphNode(uint16_t src, uint16_t target, uint16_t dist, + uint16_t angle) +{ + graph[src].push_back(graphNode(target, dist, angle)); +} + +// FUNCTION: +// addGraphNode(uint16_t src, uint16_t target, uint16_t dist, +// uint16_t angle) +// IN-PARAMETERS: +// Source node (uint16_t) +// OUT-PARAMETERS: +// None +// DESCRIPTION: +// Adds a graph node to the graph, with target, dist, and angle +// initialized to infinity +void Navigation::addGraphNode(uint16_t src) +{ + graph[src].push_back(graphNode()); +} + +// FUNCTION: +// int loadMap(char* infile); +// IN-PARAMETERS: +// Input file name (*char[]) +// OUT-PARAMETERS: +// Returns 1 if file doesn't open +// Returns 0 if file opens succesfully +// DESCRIPTION: +// Loads contents of a file as a weighted graph. First entry in the file +// should be the number of vertices. All subsequent entries indicate edges +// by listing a source vertex, a target vertex, the distance between them +// and the angle from source to target (0 - 359 degrees) . Only edges +// are listed. Assumes that inverse angles/edges are included in file. +int Navigation::loadMap(char* inputFile) +{ + std::ifstream inFile; + inFile.open(inputFile); + if (!inFile) + return 1; // returns 1 if file fails to open + + int vertices; + inFile >> vertices; // reads first entry as number of vertices + graph.resize(vertices); // resizes vector as necessary + + uint16_t src; + uint16_t target; + uint16_t dist; + uint16_t angle; + + while (!inFile.eof() ) + { + inFile >> src; + inFile >> target; + inFile >> dist; + inFile >> angle; + + addGraphNode(src, target, dist, angle); + } // loads all data from file into graph + + return 0; +} + +// FUNCTION: +// void getShortestPath(uint16_t src, uint16_t destination) +// IN-PARAMETERS: +// Target vertex (uint16_t) +// OUT-PARAMETERS: +// None +// DESCRIPTION: +// Implementation of Dijkstra's algorithm. Uses current vertex as source +// and calculates shortest path information for all other vertices. +// Subroutine ends when shortest path for target vertex has been found +// and then loads the path into route. +void Navigation::getShortestPath(uint16_t destination) +{ + uint16_t src = vertex; + uint16_t v; // stores temporary vertex + int n = graph.size(); + minDistance.clear(); + minDistance.resize(n, MAX_DIST); + minDistance[src] = 0; + previous.clear(); + previous.resize(n, -1); + std::set<std::pair<uint16_t, uint16_t> > vertex_queue; + vertex_queue.insert(std::make_pair(minDistance[src], src)); + + while (!vertex_queue.empty()) + { + uint16_t dist = vertex_queue.begin()->first; + uint16_t u = vertex_queue.begin()->second; + vertex_queue.erase(vertex_queue.begin()); + + // Visit each edge exiting u + const std::vector<graphNode> &neighbors = graph[u]; + for (std::vector<graphNode>::const_iterator neighbor_iter = neighbors.begin(); + neighbor_iter != neighbors.end(); + neighbor_iter++) + { + v = neighbor_iter->neighbor; + uint16_t weight = neighbor_iter->distance; + uint16_t distance_through_u = dist + weight; + + if (distance_through_u < minDistance[v]) + { + vertex_queue.erase(std::make_pair(minDistance[v], v)); + + minDistance[v] = distance_through_u; + previous[v] = u; + vertex_queue.insert(std::make_pair(minDistance[v], v)); + } + if (v == destination) + break; + } + if (v == destination) + break; + } + while (v != src) + { + route.push(v); + v = previous[v]; + } +} + +// utility function +void Navigation::printPrevious(Serial &pc) +{ + for(int i = 0; i < previous.size(); i++) + { + pc.printf("Node %i is prev to node %i\n", previous[i], i); + } +} + +// utility function +void Navigation::printRoute(Serial &pc) +{ + while (!route.empty() ) + { + pc.printf("Go to node %i\n", route.top() ); + route.pop(); + } +} + +// utility function +void Navigation::printGraph(Serial &pc) +{ + for (int i = 0; i < graph.size(); i++) + for (int j = 0; j < graph[i].size(); j++) + { + pc.printf("Node %i to %i = dist - %i, angle - %i\n", i, j, graph[i][j].distance, graph[i][j].angle); + } +}