Skip to content

Commit 1e5a4c0

Browse files
committed
cmt-20240921-5: +A*
+ AStar (A*)
1 parent 1d9a6ee commit 1e5a4c0

File tree

12 files changed

+303
-13
lines changed

12 files changed

+303
-13
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(CMAKE_CXX_STANDARD 11)
66
set(CMAKE_CXX_STANDARD_REQUIRED ON)
77

88
# Add subdirectories and compile separately
9+
add_subdirectory(astar)
910
add_subdirectory(monte_carlo_tree_search)
1011
add_subdirectory(rapidly_exploring_random_tree)
1112

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## Robot Path Planning
22
* [Monte Carlo Tree Search](monte_carlo_tree_search/README.md)
33
* [Rapidly Exploring Random Tree (RRT)](rapidly_exploring_random_tree/README.md)
4+
* [AStar (A*)](astar/README.md)
45

56
### Appendix: Build & Run
67
`CMakeList.txt` mainly for github workflows' building process.
@@ -21,6 +22,8 @@ Run:
2122
./monte_carlo_tree_search/mcts.so
2223
# rrt
2324
./rapidly_exploring_random_tree/rrt.so
25+
# AStar (A*)
26+
./astar/astar.so
2427
```
2528

2629
Clean:

astar/CMakeLists.txt

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(mcts_project)
3+
4+
set(CMAKE_CXX_STANDARD 11)
5+
set(CMAKE_CXX_FLAGS "-Wall")
6+
7+
# Load configs from config.properties
8+
file(READ ${CMAKE_CURRENT_LIST_DIR}/config.properties CONFIG_CONTENT)
9+
10+
string(REGEX MATCH "CONFIG_WIDTH=[0-9]+" WIDTH_MATCH ${CONFIG_CONTENT})
11+
string(REGEX MATCH "CONFIG_HEIGHT=[0-9]+" HEIGHT_MATCH ${CONFIG_CONTENT})
12+
string(REGEX MATCH "CONFIG_START_X=[0-9]+" START_X_MATCH ${CONFIG_CONTENT})
13+
string(REGEX MATCH "CONFIG_START_Y=[0-9]+" START_Y_MATCH ${CONFIG_CONTENT})
14+
string(REGEX MATCH "CONFIG_GOAL_X=[0-9]+" GOAL_X_MATCH ${CONFIG_CONTENT})
15+
string(REGEX MATCH "CONFIG_GOAL_Y=[0-9]+" GOAL_Y_MATCH ${CONFIG_CONTENT})
16+
17+
# config values
18+
string(REPLACE "CONFIG_WIDTH=" "" CONFIG_WIDTH ${WIDTH_MATCH})
19+
string(REPLACE "CONFIG_HEIGHT=" "" CONFIG_HEIGHT ${HEIGHT_MATCH})
20+
string(REPLACE "CONFIG_START_X=" "" CONFIG_START_X ${START_X_MATCH})
21+
string(REPLACE "CONFIG_START_Y=" "" CONFIG_START_Y ${START_Y_MATCH})
22+
string(REPLACE "CONFIG_GOAL_X=" "" CONFIG_GOAL_X ${GOAL_X_MATCH})
23+
string(REPLACE "CONFIG_GOAL_Y=" "" CONFIG_GOAL_Y ${GOAL_Y_MATCH})
24+
25+
# compile options
26+
add_compile_definitions(
27+
CONFIG_WIDTH=${CONFIG_WIDTH}
28+
CONFIG_HEIGHT=${CONFIG_HEIGHT}
29+
CONFIG_START_X=${CONFIG_START_X}
30+
CONFIG_START_Y=${CONFIG_START_Y}
31+
CONFIG_GOAL_X=${CONFIG_GOAL_X}
32+
CONFIG_GOAL_Y=${CONFIG_GOAL_Y}
33+
)
34+
35+
# Set dir of include, src and obj
36+
set(INCDIR ${CMAKE_SOURCE_DIR}/include)
37+
set(SRCDIR ${CMAKE_SOURCE_DIR}/src)
38+
set(OBJDIR ${CMAKE_BINARY_DIR}/obj)
39+
40+
# Set obj files and src files
41+
set(SRCFILES ${CMAKE_CURRENT_LIST_DIR}/src/astar.cpp ${CMAKE_CURRENT_LIST_DIR}/src/main.cpp)
42+
set(OBJFILES ${OBJDIR}/astar.o ${OBJDIR}/main.o)
43+
44+
# Include Dir
45+
include_directories(${INCDIR})
46+
47+
# Add an object library to control the generation of object files
48+
add_library(astar_objects OBJECT ${SRCFILES})
49+
50+
# Set the output directory to the obj folder
51+
set_target_properties(astar_objects PROPERTIES
52+
ARCHIVE_OUTPUT_DIRECTORY ${OBJDIR}
53+
LIBRARY_OUTPUT_DIRECTORY ${OBJDIR}
54+
RUNTIME_OUTPUT_DIRECTORY ${OBJDIR}
55+
)
56+
57+
# executable file
58+
add_executable(astar.so $<TARGET_OBJECTS:astar_objects>)
59+
60+
# clean
61+
add_custom_target(clean_astar
62+
COMMAND ${CMAKE_COMMAND} -E remove_directory ${OBJDIR}
63+
COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/astar.so
64+
)

astar/Makefile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
CONFIG_FILE = config.properties
2+
3+
CONFIG_WIDTH = $(shell grep ^CONFIG_WIDTH $(CONFIG_FILE) | cut -d '=' -f2)
4+
CONFIG_HEIGHT = $(shell grep ^CONFIG_HEIGHT $(CONFIG_FILE) | cut -d '=' -f2)
5+
CONFIG_START_X = $(shell grep ^CONFIG_START_X $(CONFIG_FILE) | cut -d '=' -f2)
6+
CONFIG_START_Y = $(shell grep ^CONFIG_START_Y $(CONFIG_FILE) | cut -d '=' -f2)
7+
CONFIG_GOAL_X = $(shell grep ^CONFIG_GOAL_X $(CONFIG_FILE) | cut -d '=' -f2)
8+
CONFIG_GOAL_Y = $(shell grep ^CONFIG_GOAL_Y $(CONFIG_FILE) | cut -d '=' -f2)
9+
10+
# Compiler
11+
CXX = g++
12+
CXXFLAGS = -std=c++11 -Wall -DCONFIG_WIDTH=$(CONFIG_WIDTH) -DCONFIG_HEIGHT=$(CONFIG_HEIGHT) -DCONFIG_START_X=$(CONFIG_START_X) -DCONFIG_START_Y=$(CONFIG_START_Y) -DCONFIG_GOAL_X=$(CONFIG_GOAL_X) -DCONFIG_GOAL_Y=$(CONFIG_GOAL_Y)
13+
14+
# Directories
15+
INCDIR = include
16+
SRCDIR = src
17+
OBJDIR = obj
18+
19+
# Files
20+
SRCFILES = $(SRCDIR)/astar.cpp $(SRCDIR)/main.cpp
21+
OBJFILES = $(OBJDIR)/astar.o $(OBJDIR)/main.o
22+
TARGET = astar.so
23+
24+
# Ensure the object directory exists and compile target
25+
$(TARGET): $(OBJFILES)
26+
$(CXX) $(OBJFILES) -o $(TARGET)
27+
28+
# Create object directory if not exists and compile source files into objects
29+
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)
30+
$(CXX) $(CXXFLAGS) -I$(INCDIR) -c $< -o $@
31+
32+
# Create object directory
33+
$(OBJDIR):
34+
mkdir -p $(OBJDIR)
35+
36+
# Clean up
37+
clean:
38+
rm -rf $(OBJDIR) $(TARGET)

astar/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## AStar (A*)
2+
[Original Paper](paper/astar.pdf)
3+
4+
### Appendix: Build & Run
5+
`CMakeList.txt` mainly for github workflows' building process.
6+
7+
If you want to build manually, use `Makefile` there.
8+
9+
* Build
10+
11+
```shell
12+
make
13+
```
14+
15+
* Run:
16+
17+
```shell
18+
./astar.so
19+
```
20+
21+
* Clean:
22+
23+
```shell
24+
make clean
25+
```

astar/config.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONFIG_WIDTH=7
2+
CONFIG_HEIGHT=7
3+
CONFIG_START_X=0
4+
CONFIG_START_Y=1
5+
CONFIG_GOAL_X=5
6+
CONFIG_GOAL_Y=6

astar/include/astar.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef ASTAR_H
2+
#define ASTAR_H
3+
4+
#include <vector>
5+
#include <utility>
6+
7+
struct Node {
8+
int x, y;
9+
double f, g, h;
10+
bool operator>(const Node& other) const;
11+
};
12+
13+
double heuristic(int x1, int y1, int x2, int y2);
14+
std::vector<std::pair<int, int>> getNeighbors(int x, int y, int width, int height);
15+
std::vector<std::pair<int, int>> aStar(int startX, int startY, int goalX, int goalY, int width, int height);
16+
17+
#endif // ASTAR_H

astar/paper/astar.pdf

1.21 MB
Binary file not shown.

astar/src/astar.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include "../include/astar.h"
2+
#include <queue>
3+
#include <unordered_map>
4+
#include <cmath>
5+
#include <iostream>
6+
7+
using namespace std;
8+
9+
bool Node::operator>(const Node& other) const {
10+
return f > other.f;
11+
}
12+
13+
double heuristic(int x1, int y1, int x2, int y2) {
14+
return abs(x1 - x2) + abs(y1 - y2); // Manhattan distance
15+
}
16+
17+
vector<pair<int, int>> getNeighbors(int x, int y, int width, int height) {
18+
vector<pair<int, int>> neighbors;
19+
if (x > 0) neighbors.emplace_back(x - 1, y);
20+
if (x < width - 1) neighbors.emplace_back(x + 1, y);
21+
if (y > 0) neighbors.emplace_back(x, y - 1);
22+
if (y < height - 1) neighbors.emplace_back(x, y + 1);
23+
return neighbors;
24+
}
25+
26+
void printOpenSet(priority_queue<Node, vector<Node>, greater<Node>> openSet) {
27+
cout << "Open set (nodes in queue):" << endl;
28+
while (!openSet.empty()) {
29+
Node node = openSet.top();
30+
cout << "Node(" << node.x << ", " << node.y << ") - f: " << node.f << ", g: " << node.g << ", h: " << node.h << endl;
31+
openSet.pop();
32+
}
33+
}
34+
35+
vector<pair<int, int>> aStar(int startX, int startY, int goalX, int goalY, int width, int height) {
36+
priority_queue<Node, vector<Node>, greater<Node>> openSet;
37+
unordered_map<int, Node> allNodes;
38+
vector<vector<bool>> closedSet(height, vector<bool>(width, false));
39+
40+
Node start{startX, startY, 0, 0, heuristic(startX, startY, goalX, goalY)};
41+
openSet.push(start);
42+
allNodes[startY * width + startX] = start;
43+
44+
while (!openSet.empty()) {
45+
Node current = openSet.top();
46+
openSet.pop();
47+
48+
cout << "Current node: (" << current.x << ", " << current.y << ") - f: " << current.f << ", g: " << current.g << ", h: " << current.h << endl;
49+
50+
if (current.x == goalX && current.y == goalY) {
51+
vector<pair<int, int>> path;
52+
path.emplace_back(current.x, current.y);
53+
return path; // Return path (only the target node is returned here, and the actual application needs to track the path)
54+
}
55+
56+
closedSet[current.y][current.x] = true;
57+
58+
for (const auto& neighbor : getNeighbors(current.x, current.y, width, height)) {
59+
int neighborX = neighbor.first;
60+
int neighborY = neighbor.second;
61+
62+
if (closedSet[neighborY][neighborX]) continue;
63+
64+
double tentative_g = current.g + 1; // 假设移动成本为1
65+
Node neighborNode{neighborX, neighborY, 0, tentative_g, heuristic(neighborX, neighborY, goalX, goalY)};
66+
67+
if (allNodes.find(neighborY * width + neighborX) == allNodes.end() || tentative_g < allNodes[neighborY * width + neighborX].g) {
68+
neighborNode.f = neighborNode.g + neighborNode.h;
69+
allNodes[neighborY * width + neighborX] = neighborNode;
70+
openSet.push(neighborNode);
71+
}
72+
}
73+
74+
// 打印当前优先队列中的节点
75+
printOpenSet(openSet);
76+
cout << "-------------------------------" << endl;
77+
}
78+
79+
return {}; // No path found
80+
}

astar/src/main.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include <iostream>
2+
#include "../include/astar.h"
3+
4+
#ifndef CONFIG_WIDTH
5+
#define CONFIG_WIDTH 5
6+
#endif
7+
constexpr int WIDTH = CONFIG_WIDTH;
8+
9+
#ifndef CONFIG_HEIGHT
10+
#define CONFIG_HEIGHT 5
11+
#endif
12+
constexpr int HEIGHT = CONFIG_HEIGHT;
13+
14+
#ifndef CONFIG_START_X
15+
#define CONFIG_START_X 0
16+
#endif
17+
constexpr int START_X = CONFIG_START_X;
18+
19+
#ifndef CONFIG_START_Y
20+
#define CONFIG_START_Y 0
21+
#endif
22+
constexpr int START_Y = CONFIG_START_Y;
23+
24+
#ifndef CONFIG_GOAL_X
25+
#define CONFIG_GOAL_X 4
26+
#endif
27+
constexpr int GOAL_X = CONFIG_GOAL_X;
28+
29+
#ifndef CONFIG_GOAL_Y
30+
#define CONFIG_GOAL_Y 4
31+
#endif
32+
constexpr int GOAL_Y = CONFIG_GOAL_Y;
33+
34+
int main() {
35+
int width = WIDTH, height = HEIGHT;
36+
std::vector<std::pair<int, int>> path = aStar(START_X, START_Y, GOAL_X, GOAL_Y, width, height);
37+
38+
if (!path.empty()) {
39+
std::cout << "Path found: ";
40+
for (const auto& p : path) {
41+
std::cout << "(" << p.first << ", " << p.second << ") \n";
42+
}
43+
} else {
44+
std::cout << "No path found!\n";
45+
}
46+
47+
return 0;
48+
}

monte_carlo_tree_search/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ set(OBJDIR ${CMAKE_BINARY_DIR}/obj)
3636

3737
# Set obj files and src files
3838
set(SRCFILES ${CMAKE_CURRENT_LIST_DIR}/src/state.cpp ${CMAKE_CURRENT_LIST_DIR}/src/mcts.cpp ${CMAKE_CURRENT_LIST_DIR}/src/main.cpp)
39-
set(OBJFILES ${OBJDIR}/mcts.o ${OBJDIR}/main.o)
39+
set(OBJFILES ${OBJDIR}/state.o ${OBJDIR}/mcts.o ${OBJDIR}/main.o)
4040

4141
# Include Dir
4242
include_directories(${INCDIR})

monte_carlo_tree_search/Makefile

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,32 @@ CONFIG_GOAL_Y = $(shell grep ^CONFIG_GOAL_Y $(CONFIG_FILE) | cut -d '=' -f2)
66
CONFIG_MAX_SIM_STEPS = $(shell grep ^CONFIG_MAX_SIM_STEPS $(CONFIG_FILE) | cut -d '=' -f2)
77
CONFIG_C = $(shell grep ^CONFIG_C $(CONFIG_FILE) | cut -d '=' -f2)
88

9+
# Compiler
910
CXX = g++
1011
CXXFLAGS = -std=c++11 -Wall -DCONFIG_GRID_SIZE=$(CONFIG_GRID_SIZE) -DCONFIG_GOAL_X=$(CONFIG_GOAL_X) -DCONFIG_GOAL_Y=$(CONFIG_GOAL_Y) -DCONFIG_MAX_SIM_STEPS=$(CONFIG_MAX_SIM_STEPS) -DCONFIG_C=$(CONFIG_C)
1112

12-
# exe file name
13-
TARGET = mcts.so
13+
# Directories
14+
INCDIR = include
15+
SRCDIR = src
16+
OBJDIR = obj
1417

15-
# source file
16-
SRC = src/main.cpp src/mcts.cpp src/state.cpp
18+
# Files
19+
SRCFILES = $(SRCDIR)/state.cpp $(SRCDIR)/mcts.cpp $(SRCDIR)/main.cpp
20+
OBJFILES = $(OBJDIR)/state.o $(OBJDIR)/mcts.o $(OBJDIR)/main.o
21+
TARGET = mcts.so
1722

18-
# header file
19-
HDR = include/mcts.h include/state.h
23+
# Ensure the object directory exists and compile target
24+
$(TARGET): $(OBJFILES)
25+
$(CXX) $(OBJFILES) -o $(TARGET)
2026

21-
# compile rules
22-
all: $(TARGET)
27+
# Create object directory if not exists and compile source files into objects
28+
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)
29+
$(CXX) $(CXXFLAGS) -I$(INCDIR) -c $< -o $@
2330

24-
$(TARGET): $(SRC) $(HDR)
25-
$(CXX) $(CXXFLAGS) -o $(TARGET) $(SRC)
31+
# Create object directory
32+
$(OBJDIR):
33+
mkdir -p $(OBJDIR)
2634

27-
# clear all out files
35+
# Clean up
2836
clean:
29-
rm -f $(TARGET)
37+
rm -rf $(OBJDIR) $(TARGET)

0 commit comments

Comments
 (0)