├── AStarPlanner.py
├── LICENSE
├── README.md
├── Vplanner.py
├── dwa.py
├── gazebo
├── CMakeLists.txt
├── course_agv_control
│ ├── CMakeLists.txt
│ ├── config
│ │ └── course_agv_control.yaml
│ ├── launch
│ │ └── course_agv_control.launch
│ ├── package.xml
│ └── scripts
│ │ ├── keyboard_velocity.py
│ │ └── kinematics.py
├── course_agv_description
│ ├── CMakeLists.txt
│ ├── launch
│ │ ├── course_agv.rviz
│ │ └── course_agv_rviz.launch
│ ├── meshes
│ │ └── hokuyo.dae
│ ├── package.xml
│ └── urdf
│ │ ├── course_agv.gazebo
│ │ ├── course_agv.xacro
│ │ └── materials.xacro
├── course_agv_gazebo
│ ├── CMakeLists.txt
│ ├── config
│ │ ├── map.yaml
│ │ └── map
│ │ │ ├── map.png
│ │ │ └── map_backup2.png
│ ├── launch
│ │ ├── course_agv.rviz
│ │ ├── course_agv_world.launch
│ │ └── course_agv_world_rviz.launch
│ ├── models
│ │ └── ground_plane_for_agv
│ │ │ ├── map
│ │ │ ├── map.png
│ │ │ └── map_backup2.png
│ │ │ ├── materials
│ │ │ └── textures
│ │ │ │ ├── flat_normal.png
│ │ │ │ └── grey.png
│ │ │ ├── model.config
│ │ │ └── model.sdf
│ ├── package.xml
│ ├── scripts
│ │ └── robot_tf.py
│ └── worlds
│ │ └── course_agv.world
└── course_agv_nav
│ ├── CMakeLists.txt
│ ├── launch
│ ├── nav.launch
│ └── nav.rviz
│ ├── package.xml
│ ├── scripts
│ ├── A_star.py
│ ├── RRT_plan.py
│ ├── RRT_rewire.py
│ ├── __pycache__
│ │ ├── A_star.cpython-39.pyc
│ │ └── dwaplanner.cpython-39.pyc
│ ├── dwaplanner.py
│ ├── global_planner.py
│ └── local_planner.py
│ └── srv
│ └── Plan.srv
└── main.py
/AStarPlanner.py:
--------------------------------------------------------------------------------
1 | from heapq import heappush, heappop
2 | from numpy import sqrt
3 | import numpy as np
4 | class AStarPlanner:
5 | def __init__(self, unit_step = 0.1):
6 | self.unit_step = unit_step
7 | def planning(self, planning_obs_x, planning_obs_y, planning_obs_radius, planning_start_x, planning_start_y, planning_target_x, planning_target_y, planning_minx, planning_miny, planning_maxx, planning_maxy):
8 | heap = []
9 | # 离散化
10 | planning_start_x_int = int((planning_start_x - planning_minx) / self.unit_step)
11 | planning_start_y_int = int((planning_start_y - planning_miny) / self.unit_step)
12 | planning_target_x_int = int((planning_target_x - planning_minx) / self.unit_step)
13 | planning_target_y_int = int((planning_target_y - planning_miny) / self.unit_step)
14 | planning_max_x_int = int((planning_maxx - planning_minx) / self.unit_step)
15 | planning_max_y_int = int((planning_maxy - planning_miny) / self.unit_step)
16 | map = np.zeros((planning_max_x_int, planning_max_y_int))
17 |
18 | # 设置障碍物
19 | planning_obs_radius *= 1.0
20 | obs_radius_int = int(planning_obs_radius / self.unit_step)
21 | for i in range(planning_obs_x.shape[0]):
22 | obs_x_int = int((planning_obs_x[i] - planning_minx) / self.unit_step)
23 | obs_y_int = int((planning_obs_y[i] - planning_miny) / self.unit_step)
24 | for x in range(obs_x_int - obs_radius_int, obs_x_int + obs_radius_int):
25 | for y in range(obs_y_int - obs_radius_int, obs_y_int + obs_radius_int):
26 | real_x = planning_minx + x * self.unit_step
27 | real_y = planning_miny + y * self.unit_step
28 | if x >= 0 and x < planning_max_x_int and y >= 0 and y < planning_max_y_int and (real_x - planning_obs_x[i]) ** 2 + (real_y - planning_obs_y[i]) ** 2 <= obs_radius_int ** 2:
29 | map[x, y] = 1
30 |
31 | # 初始化
32 | heappush(heap, (0, planning_start_x_int, planning_start_y_int))
33 | came_from = {}
34 | cost_so_far = {}
35 | # came_from[(planning_start_x_int, planning_start_y_int)] = None
36 | cost_so_far[(planning_start_x_int, planning_start_y_int)] = 0
37 | while len(heap) > 0:
38 | current = heappop(heap)
39 | # 如果已经到达目标点,直接返回
40 | if current[1] == planning_target_x_int and current[2] == planning_target_y_int:
41 | break
42 | #只允许上下左右,斜向走
43 | for next in [(current[1] + 1, current[2]), (current[1] - 1, current[2]), (current[1], current[2] + 1), (current[1], current[2] - 1), (current[1] + 1, current[2] + 1), (current[1] - 1, current[2] - 1), (current[1] + 1, current[2] - 1), (current[1] - 1, current[2] + 1)]:
44 | # 若超出地图范围,则跳过
45 | if next[0] < 0 or next[0] >= planning_max_x_int or next[1] < 0 or next[1] >= planning_max_y_int:
46 | continue
47 | # 换算next实际坐标
48 | next_x = next[0] * self.unit_step + planning_minx
49 | next_y = next[1] * self.unit_step + planning_miny
50 | # 若为障碍物,则跳过
51 | if map[next[0], next[1]] == 1:
52 | continue
53 | # if ((next_x - planning_obs_x) ** 2 + (next_y - planning_obs_y) ** 2 <= planning_obs_radius ** 2).any():
54 | # continue
55 | # for i in range(len(planning_obs_x)):
56 | # if (next_x - planning_obs_x[i]) ** 2 + (next_y - planning_obs_y[i]) ** 2 < planning_obs_radius ** 2:
57 | # continue
58 | # 换算current实际坐标
59 | current_x = current[1] * self.unit_step + planning_minx
60 | current_y = current[2] * self.unit_step + planning_miny
61 | # 计算新的cost,因为只允许向四个方向走,不加根号也可以!!!!!!!!!!!!!!!(加上了斜向走,所以不加根号不可以)
62 | new_cost = cost_so_far[(current[1], current[2])] + np.sqrt((next_x - current_x) ** 2 + (next_y - current_y) ** 2)
63 | if next not in cost_so_far or new_cost < cost_so_far[next]:
64 | cost_so_far[next] = new_cost
65 | #这里也忘了sqrt
66 | priority = new_cost + sqrt((planning_target_x - next_x) ** 2 + (planning_target_y - next_y) ** 2)
67 | heappush(heap, (priority, next[0], next[1]))
68 | came_from[next] = (current[1], current[2])
69 | #如果到达不了
70 | if (planning_target_x_int, planning_target_y_int) not in cost_so_far:
71 | return [],[]
72 | #回溯路径,返回的是非离散空间的路径
73 | current = (planning_target_x_int, planning_target_y_int)
74 | path = []
75 | while current in came_from:
76 | path.append((current[0] * self.unit_step + planning_minx, current[1] * self.unit_step + planning_miny))
77 | current = came_from[current]
78 | path.append((planning_start_x, planning_start_y))
79 | path.reverse()
80 | pathnp = np.array(path)
81 | return pathnp[:,0], pathnp[:,1]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 kaliv
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Robot
2 | - 实现Astar算法和DWA算法的结合
3 | 1. main.py: 文件可以通过Astar算法实现两点间的路径规划
4 | 2. dwa.py: 文件在main.py文件的基础上增加了dwa动态窗口算法,可以实现小车在运行过程中动态避障功能
5 | 3. Vplanner.py: dwa算法实现
6 | 4. AStarPlanner.py: astar算法实现
7 |
8 | - 关键控制指令:
9 | 1. 按下鼠标左键放置起始点
10 | 2. 按下鼠标右键放置终点
11 | 3. 按下鼠标中键放置障碍物
12 | 4. 按下空格键开始规划路径
13 |
14 |
15 | ## Astar算法实现的示意图
16 |
17 |
18 |
19 |
20 |
21 | ## dwa算法实现的示意图
22 |
23 |
24 | ## dwa算法带雷达显示
25 |
26 |
27 |
28 |
29 | 由于dwa算法的缺陷,容易陷入局部最优解,改进的方法是在上述情况下重新规划路径,实现动态dwa
30 |
31 | ## Gazebo仿真环境
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Vplanner.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class DWA():
5 | def __init__(self):
6 | pass
7 |
8 | def plan(self, x, info, midpos, planning_obs):
9 | vw = self.vw_generate(x, info)
10 | min_score = 1000.0
11 | # 速度v,w都被限制在速度空间里
12 | all_ctral = []
13 | all_scores = []
14 | for v in np.arange(vw[0], vw[1], info.v_reso):
15 | for w in np.arange(vw[2], vw[3], info.yawrate_reso):
16 | # cauculate traj for each given (v,w)
17 | ctraj = self.traj_cauculate(x, [v, w], info)
18 | # 计算评价函数
19 | goal_score = info.to_goal_cost_gain * \
20 | self.goal_evaluate(ctraj, midpos)
21 | vel_score = info.speed_cost_gain * \
22 | self.velocity_evaluate(ctraj, info)
23 | traj_score = info.obstacle_cost_gain * \
24 | self.traj_evaluate(ctraj, planning_obs, info)
25 | # 可行路径不止一条,通过评价函数确定最佳路径
26 | # 路径总分数 = 距离目标点 + 速度 + 障碍物
27 | # 分数越低,路径越优
28 | ctraj_score = goal_score + vel_score + traj_score
29 | # print(goal_score, vel_score, traj_score)
30 |
31 | ctraj = np.reshape(ctraj, (-1, 5))
32 |
33 | # evaluate current traj (the score smaller,the traj better)
34 | if min_score >= ctraj_score:
35 | min_score = ctraj_score
36 | u = np.array([v, w])
37 | best_ctral = ctraj
38 | all_ctral.append(ctraj)
39 | all_scores.append(ctraj_score)
40 |
41 |
42 | return u, best_ctral, all_ctral, all_scores
43 |
44 | # 定义机器人运动模型
45 | # 返回坐标(x,y),偏移角theta,速度v,角速度w
46 | def motion_model(self, x, u, dt):
47 | # robot motion model: x,y,theta,v,w
48 | x[0] += u[0] * dt * np.cos(x[2])
49 | x[1] += u[0] * dt * np.sin(x[2])
50 | x[2] += u[1] * dt
51 | x[3] = u[0]
52 | x[4] = u[1]
53 | return x
54 |
55 | # 依据当前位置及速度,预测轨迹
56 | def traj_cauculate(self, x, u, info):
57 | ctraj = np.array(x)
58 | xnew = np.array(x)
59 | time = 0
60 |
61 | while time <= info.predict_time: # preditc_time作用
62 | xnew = self.motion_model(xnew, u, info.dt)
63 | ctraj = np.vstack([ctraj, xnew])
64 | time += info.dt
65 |
66 | # print(ctraj)
67 | return ctraj
68 |
69 |
70 |
71 | # 产生速度空间
72 | def vw_generate(self, x, info):
73 | # generate v,w window for traj prediction
74 | Vinfo = [info.min_speed, info.max_speed,
75 | info.min_yawrate, info.max_yawrate]
76 |
77 | Vmove = [x[3] - info.max_accel * info.dt,
78 | x[3] + info.max_accel * info.dt,
79 | x[4] - info.max_dyawrate * info.dt,
80 | x[4] + info.max_dyawrate * info.dt]
81 |
82 | # 保证速度变化不超过info限制的范围
83 | vw = [max(Vinfo[0], Vmove[0]), min(Vinfo[1], Vmove[1]),
84 | max(Vinfo[2], Vmove[2]), min(Vinfo[3], Vmove[3])]
85 |
86 | return vw
87 |
88 | # 距离目标点评价函数
89 | def goal_evaluate(self, traj, goal):
90 | # cauculate current pose to goal with euclidean distance
91 | goal_score = np.sqrt((traj[-1, 0]-goal[0]) **
92 | 2 + (traj[-1, 1]-goal[1])**2)
93 | return goal_score
94 |
95 | # 速度评价函数
96 | def velocity_evaluate(self, traj, info):
97 | # cauculate current velocty score
98 | vel_score = info.max_speed - traj[-1, 3]
99 | return vel_score
100 |
101 | # 轨迹距离障碍物的评价函数
102 | def traj_evaluate(self, traj, obstacles, info):
103 | # evaluate current traj with the min distance to obstacles
104 | min_dis = float("Inf")
105 | for i in range(len(traj)):
106 | for ii in range(len(obstacles)):
107 | current_dist = np.sqrt(
108 | (traj[i, 0] - obstacles[ii, 0])**2 + (traj[i, 1] - obstacles[ii, 1])**2)
109 |
110 | if current_dist <= 0.75:
111 | return float("Inf")
112 |
113 | if min_dis >= current_dist:
114 | min_dis = current_dist
115 |
116 | return 1 / min_dis
117 |
--------------------------------------------------------------------------------
/dwa.py:
--------------------------------------------------------------------------------
1 | import time
2 | import math
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | from AStarPlanner import AStarPlanner
7 | from Vplanner import DWA
8 |
9 | # from planner import AStarPlanner,RRTPlanner
10 | # from localplanner import dwa
11 |
12 | plt.rcParams["figure.figsize"] = [8.0, 8.0]
13 | plt.rcParams["figure.autolayout"] = True
14 | plt.rcParams['keymap.save'].remove('s')
15 |
16 |
17 | def transformation_matrix(x, y, theta):
18 | return np.array([
19 | [np.cos(theta), -np.sin(theta), x],
20 | [np.sin(theta), np.cos(theta), y],
21 | [0, 0, 1]
22 | ])
23 |
24 |
25 | class DWAConfig:
26 | robot_radius = 0.25
27 |
28 | def __init__(self, obs_radius):
29 | self.obs_radius = obs_radius
30 | self.dt = 0.1 # [s] Time tick for motion prediction
31 |
32 | self.max_speed = 1.5 # [m/s] 最大线速度
33 | self.min_speed = -0.5 # [m/s] 最小线速度
34 | self.max_accel = 0.5 # [m/ss] 加速度
35 | self.v_reso = self.max_accel*self.dt/10.0 # [m/s] 速度增加的步长
36 |
37 | self.min_yawrate = -100.0 * math.pi / 180.0 # [rad/s] 最小角速度
38 | self.max_yawrate = 100.0 * math.pi / 180.0 # [rad/s] 最大角速度
39 | self.max_dyawrate = 500.0 * math.pi / 180.0 # [rad/ss] 角加速度
40 | self.yawrate_reso = self.max_dyawrate*self.dt/10.0 # [rad/s] 角速度增加的步长
41 |
42 | # 模拟轨迹的持续时间
43 | self.predict_time = 2 # [s]
44 |
45 | # 三个比例系数
46 | self.to_goal_cost_gain = 1.0 # 距离目标点的评价函数的权重系数
47 | self.speed_cost_gain = 0.7 # 速度评价函数的权重系数
48 | self.obstacle_cost_gain = 1.0 # 距离障碍物距离的评价函数的权重系数
49 |
50 | self.tracking_dist = self.predict_time*self.max_speed
51 | self.arrive_dist = 0.1
52 |
53 |
54 | class Playground:
55 | planning_obs_radius = 0.5
56 |
57 | def __init__(self, planner=None, vplanner=None):
58 | self.x = 0.0
59 | self.y = 0.0
60 | self.theta = 0.0
61 | self.vx = 0.0
62 | self.vw = 0.0
63 | self.x_traj = []
64 | self.y_traj = []
65 |
66 | self.dwaconfig = DWAConfig(self.planning_obs_radius)
67 | self.dt = self.dwaconfig.dt
68 |
69 | self.fig, self.ax = plt.subplots()
70 |
71 | self.fig.canvas.mpl_connect('button_press_event', self.on_mousepress)
72 | self.fig.canvas.mpl_connect('key_press_event', self.on_press)
73 | self.fig.canvas.mpl_connect('motion_notify_event', self.on_mousemove)
74 | self.NEED_EXIT = False
75 |
76 | ############################################
77 |
78 | self.planning_obs = np.empty(shape=(0, 2))
79 |
80 | self.planning_path = np.empty(shape=(0, 2))
81 |
82 | self.planning_target = None
83 |
84 | self.planner = planner
85 | self.vplanner = vplanner
86 |
87 | self.vplanner_midpos_index = None
88 |
89 | #####################################
90 | self.temp_obs = [0, 0]
91 |
92 | def run(self):
93 | while True:
94 | if self.NEED_EXIT:
95 | plt.close("all")
96 | break
97 | self.vplanner_midpos_index = self.check_path()
98 | all_traj = []
99 | all_u = []
100 | best_traj = None
101 | if self.vplanner_midpos_index >= 0:
102 | midpos = self.planning_path[self.vplanner_midpos_index]
103 | [self.vx,self.vw], best_traj, all_traj, all_u = self.vplanner.plan([self.x,self.y,self.theta,self.vx,self.vw],
104 | self.dwaconfig,midpos,self.planning_obs)
105 | else:
106 | self.vx, self.vw = 0.0, 0.0
107 |
108 | dx, dy, dw = self.vx*self.dt, 0, self.vw*self.dt
109 | T = transformation_matrix(self.x, self.y, self.theta)
110 | p = np.matmul(T, np.array([dx, dy, 1]))
111 | self.x = p[0]
112 | self.y = p[1]
113 | self.theta += dw
114 | self.x_traj.append(self.x)
115 | self.y_traj.append(self.y)
116 |
117 | plt.cla()
118 | self.__draw(all_traj, all_u, best_traj=best_traj)
119 |
120 | def check_path(self):
121 | if self.planning_path is None or self.planning_path.shape[0] == 0:
122 | return -1
123 | if self.vplanner_midpos_index is not None and self.vplanner_midpos_index >= 0:
124 | midindex = self.vplanner_midpos_index
125 | while True:
126 | midpos = self.planning_path[midindex]
127 | dist = np.hypot(self.x-midpos[0], self.y-midpos[1])
128 | if dist > self.dwaconfig.tracking_dist:
129 | break
130 | if midindex + 1 == self.planning_path.shape[0]:
131 | return midindex
132 | midindex += 1
133 | return midindex
134 | else:
135 | return 0
136 |
137 | def add_obs(self, x, y):
138 | self.planning_obs = np.append(self.planning_obs, [[x, y]], axis=0)
139 |
140 | def add_obss(self, xs, ys):
141 | self.planning_obs = np.append(
142 | self.planning_obs, np.vstack([xs, ys]).T, axis=0)
143 |
144 | def __draw(self, all_traj, all_value, best_traj):
145 | assert(self.planning_path is None or self.planning_path.shape[1] == 2,
146 | "the shape of planning path should be '[x,2]', please check your algorithm.")
147 | assert(self.planning_obs is None or self.planning_obs.shape[1] == 2,
148 | "the shape of self.planning_obs(obstacles) should be '[x,2]', please check your algorithm.")
149 |
150 | p1_i = np.array([0.5, 0, 1]).T
151 | p2_i = np.array([-0.5, 0.25, 1]).T
152 | p3_i = np.array([-0.5, -0.25, 1]).T
153 |
154 | T = transformation_matrix(self.x, self.y, self.theta)
155 | p1 = np.matmul(T, p1_i)
156 | p2 = np.matmul(T, p2_i)
157 | p3 = np.matmul(T, p3_i)
158 |
159 | plt.plot([p1[0], p2[0], p3[0], p1[0]], [
160 | p1[1], p2[1], p3[1], p1[1]], 'k-')
161 |
162 | if self.planning_target is not None:
163 | self.ax.plot(
164 | self.planning_target[0], self.planning_target[1], "r*", markersize=20)
165 |
166 | if len(all_traj) > 0:
167 | all_value = np.array(all_value,dtype=float)
168 | all_value = (all_value-all_value.min())/(all_value.max()-all_value.min())
169 | for i,traj in enumerate(all_traj):
170 | color = plt.cm.jet(all_value[i])
171 | self.ax.plot(traj[:,0],traj[:,1],".",color=color,markersize=1)
172 | self.ax.plot(traj[-1,0],traj[-1,1],"+",color=color,markersize=3)
173 |
174 | if best_traj is not None:
175 | self.ax.plot(best_traj[:,0],best_traj[:,1],color="green",linewidth=3)
176 |
177 | if self.planning_path is not None:
178 | self.ax.plot(self.planning_path[:, 0],
179 | self.planning_path[:, 1], 'b--')
180 | if self.vplanner_midpos_index is not None and self.vplanner_midpos_index >= 0:
181 | midpos = self.planning_path[self.vplanner_midpos_index]
182 | self.ax.plot(midpos[0], midpos[1], "g+", markersize=20)
183 | if len(self.x_traj) > 0:
184 | plt.plot(self.x_traj, self.y_traj, 'g-')
185 | for obs in self.planning_obs:
186 | self.ax.add_artist(plt.Circle(
187 | (obs[0], obs[1]), self.planning_obs_radius, fill=False))
188 |
189 | self.ax.set_xlim(-10, 10)
190 | self.ax.set_ylim(-10, 10)
191 |
192 | plt.pause(self.dt)
193 |
194 | def on_mousepress(self, event):
195 | if not event.dblclick:
196 | if event.button == 1:
197 | self.x, self.y = event.xdata, event.ydata
198 | if event.button == 3:
199 | self.planning_target = np.array([event.xdata, event.ydata])
200 | if event.button == 2:
201 | self.add_obs(event.xdata, event.ydata)
202 | self.temp_obs = [event.xdata, event.ydata]
203 |
204 | def on_mousemove(self, event):
205 | if hasattr(event, "button") and event.button == 2:
206 | dx = event.xdata-self.temp_obs[0]
207 | dy = event.ydata-self.temp_obs[1]
208 | if np.hypot(dx, dy) > self.planning_obs_radius*0.8:
209 | self.temp_obs = [event.xdata, event.ydata]
210 | self.add_obs(*self.temp_obs)
211 |
212 | def on_press(self, event):
213 | if(event.key == 'escape'):
214 | self.set_exit()
215 | if(event.key == ' '):
216 | self.planning_path = None
217 | self.x_traj, self.y_traj = [], []
218 | self.vplanner_midpos_index = None
219 | if self.planning_target is not None and self.planner is not None:
220 | print("do planning...")
221 | px, py = planner.planning(self.planning_obs[:, 0], self.planning_obs[:, 1], Playground.planning_obs_radius +
222 | DWAConfig.robot_radius, self.x, self.y, self.planning_target[0], self.planning_target[1], -10, -10, 10, 10)
223 | self.planning_path = np.vstack([px, py]).T
224 | print("pathLength : ", self.planning_path.shape[0])
225 |
226 | def set_exit(self):
227 | self.NEED_EXIT = True
228 |
229 |
230 | if __name__ == "__main__":
231 | planner = None
232 | planner = AStarPlanner(0.2)
233 | vplanner = DWA()
234 | # planner = RRTPlanner(0.2,1.5)
235 | pg = Playground(planner, vplanner)
236 | pg.run()
237 |
--------------------------------------------------------------------------------
/gazebo/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | /opt/ros/noetic/share/catkin/cmake/toplevel.cmake
--------------------------------------------------------------------------------
/gazebo/course_agv_control/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(course_agv_control)
3 |
4 | ## Compile as C++11, supported in ROS Kinetic and newer
5 | # add_compile_options(-std=c++11)
6 |
7 | ## Find catkin macros and libraries
8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
9 | ## is used, also find other catkin packages
10 | find_package(catkin REQUIRED)
11 |
12 | ## System dependencies are found with CMake's conventions
13 | # find_package(Boost REQUIRED COMPONENTS system)
14 |
15 |
16 | ## Uncomment this if the package has a setup.py. This macro ensures
17 | ## modules and global scripts declared therein get installed
18 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
19 | # catkin_python_setup()
20 |
21 | ################################################
22 | ## Declare ROS messages, services and actions ##
23 | ################################################
24 |
25 | ## To declare and build messages, services or actions from within this
26 | ## package, follow these steps:
27 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in
28 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
29 | ## * In the file package.xml:
30 | ## * add a build_depend tag for "message_generation"
31 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
32 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
33 | ## but can be declared for certainty nonetheless:
34 | ## * add a exec_depend tag for "message_runtime"
35 | ## * In this file (CMakeLists.txt):
36 | ## * add "message_generation" and every package in MSG_DEP_SET to
37 | ## find_package(catkin REQUIRED COMPONENTS ...)
38 | ## * add "message_runtime" and every package in MSG_DEP_SET to
39 | ## catkin_package(CATKIN_DEPENDS ...)
40 | ## * uncomment the add_*_files sections below as needed
41 | ## and list every .msg/.srv/.action file to be processed
42 | ## * uncomment the generate_messages entry below
43 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
44 |
45 | ## Generate messages in the 'msg' folder
46 | # add_message_files(
47 | # FILES
48 | # Message1.msg
49 | # Message2.msg
50 | # )
51 |
52 | ## Generate services in the 'srv' folder
53 | # add_service_files(
54 | # FILES
55 | # Service1.srv
56 | # Service2.srv
57 | # )
58 |
59 | ## Generate actions in the 'action' folder
60 | # add_action_files(
61 | # FILES
62 | # Action1.action
63 | # Action2.action
64 | # )
65 |
66 | ## Generate added messages and services with any dependencies listed here
67 | # generate_messages(
68 | # DEPENDENCIES
69 | # std_msgs # Or other packages containing msgs
70 | # )
71 |
72 | ################################################
73 | ## Declare ROS dynamic reconfigure parameters ##
74 | ################################################
75 |
76 | ## To declare and build dynamic reconfigure parameters within this
77 | ## package, follow these steps:
78 | ## * In the file package.xml:
79 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
80 | ## * In this file (CMakeLists.txt):
81 | ## * add "dynamic_reconfigure" to
82 | ## find_package(catkin REQUIRED COMPONENTS ...)
83 | ## * uncomment the "generate_dynamic_reconfigure_options" section below
84 | ## and list every .cfg file to be processed
85 |
86 | ## Generate dynamic reconfigure parameters in the 'cfg' folder
87 | # generate_dynamic_reconfigure_options(
88 | # cfg/DynReconf1.cfg
89 | # cfg/DynReconf2.cfg
90 | # )
91 |
92 | ###################################
93 | ## catkin specific configuration ##
94 | ###################################
95 | ## The catkin_package macro generates cmake config files for your package
96 | ## Declare things to be passed to dependent projects
97 | ## INCLUDE_DIRS: uncomment this if your package contains header files
98 | ## LIBRARIES: libraries you create in this project that dependent projects also need
99 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need
100 | ## DEPENDS: system dependencies of this project that dependent projects also need
101 | catkin_package(
102 | # INCLUDE_DIRS include
103 | # LIBRARIES course_agv_control
104 | # CATKIN_DEPENDS other_catkin_pkg
105 | # DEPENDS system_lib
106 | )
107 |
108 | ###########
109 | ## Build ##
110 | ###########
111 |
112 | ## Specify additional locations of header files
113 | ## Your package locations should be listed before other locations
114 | include_directories(
115 | # include
116 | # ${catkin_INCLUDE_DIRS}
117 | )
118 |
119 | ## Declare a C++ library
120 | # add_library(${PROJECT_NAME}
121 | # src/${PROJECT_NAME}/course_agv_control.cpp
122 | # )
123 |
124 | ## Add cmake target dependencies of the library
125 | ## as an example, code may need to be generated before libraries
126 | ## either from message generation or dynamic reconfigure
127 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
128 |
129 | ## Declare a C++ executable
130 | ## With catkin_make all packages are built within a single CMake context
131 | ## The recommended prefix ensures that target names across packages don't collide
132 | # add_executable(${PROJECT_NAME}_node src/course_agv_control_node.cpp)
133 |
134 | ## Rename C++ executable without prefix
135 | ## The above recommended prefix causes long target names, the following renames the
136 | ## target back to the shorter version for ease of user use
137 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
138 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
139 |
140 | ## Add cmake target dependencies of the executable
141 | ## same as for the library above
142 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
143 |
144 | ## Specify libraries to link a library or executable target against
145 | # target_link_libraries(${PROJECT_NAME}_node
146 | # ${catkin_LIBRARIES}
147 | # )
148 |
149 | #############
150 | ## Install ##
151 | #############
152 |
153 | # all install targets should use catkin DESTINATION variables
154 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
155 |
156 | ## Mark executable scripts (Python etc.) for installation
157 | ## in contrast to setup.py, you can choose the destination
158 | # install(PROGRAMS
159 | # scripts/my_python_script
160 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
161 | # )
162 |
163 | ## Mark executables for installation
164 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
165 | # install(TARGETS ${PROJECT_NAME}_node
166 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
167 | # )
168 |
169 | ## Mark libraries for installation
170 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
171 | # install(TARGETS ${PROJECT_NAME}
172 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
173 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
174 | # RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
175 | # )
176 |
177 | ## Mark cpp header files for installation
178 | # install(DIRECTORY include/${PROJECT_NAME}/
179 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
180 | # FILES_MATCHING PATTERN "*.h"
181 | # PATTERN ".svn" EXCLUDE
182 | # )
183 |
184 | ## Mark other files for installation (e.g. launch and bag files, etc.)
185 | # install(FILES
186 | # # myfile1
187 | # # myfile2
188 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
189 | # )
190 |
191 | #############
192 | ## Testing ##
193 | #############
194 |
195 | ## Add gtest based cpp test target and link libraries
196 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_course_agv_control.cpp)
197 | # if(TARGET ${PROJECT_NAME}-test)
198 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
199 | # endif()
200 |
201 | ## Add folders to be run by python nosetests
202 | # catkin_add_nosetests(test)
203 |
--------------------------------------------------------------------------------
/gazebo/course_agv_control/config/course_agv_control.yaml:
--------------------------------------------------------------------------------
1 | course_agv:
2 | # Publish all joint states -----------------------------------
3 | joint_state_controller:
4 | type: joint_state_controller/JointStateController
5 | publish_rate: 50
6 |
7 | # Velocity Controllers ---------------------------------------
8 | left_wheel_velocity_controller:
9 | type: velocity_controllers/JointVelocityController
10 | joint: course_agv__left_wheel_joint
11 | # pid: {p: 100.0, i: 0.01, d: 10.0}
12 | right_wheel_velocity_controller:
13 | type: velocity_controllers/JointVelocityController
14 | joint: course_agv__right_wheel_joint
15 | # pid: {p: 100.0, i: 0.01, d: 10.0}
16 | gazebo_ros_control/pid_gains:
17 | course_agv__left_wheel_joint: {p: 5.0, i: 0.1, d: 0.0}
18 | course_agv__right_wheel_joint: {p: 5.0, i: 0.1, d: 0.0}
19 |
--------------------------------------------------------------------------------
/gazebo/course_agv_control/launch/course_agv_control.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/gazebo/course_agv_control/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | course_agv_control
4 | 0.0.0
5 | The course_agv_control package
6 |
7 |
8 |
9 |
10 | zjunlict
11 |
12 |
13 |
14 |
15 |
16 | TODO
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | catkin
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/gazebo/course_agv_control/scripts/keyboard_velocity.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import rospy
4 | from pynput.keyboard import Key, Listener
5 | import geometry_msgs.msg
6 |
7 | command = {
8 | "vx":0.0,
9 | "vw":0.0,
10 | "step":0.1,
11 | "vmax":3.0
12 | }
13 | def limitNum(num,minNum,maxNum):
14 | if num > maxNum:
15 | return maxNum
16 | if num < minNum:
17 | return minNum
18 | return num
19 | def cmd_num_func(cmd,key,value,minValue,maxValue):
20 | def function():
21 | cmd[key] = limitNum(cmd[key]+value,minValue,maxValue)
22 | return function
23 | def cmd_reset_func(cmd):
24 | def function():
25 | cmd["vx"] = 0
26 | cmd["vw"] = 0
27 | return function
28 | KEY_MAP_TABLE={
29 | 'w' : cmd_num_func(command,"vx", command["step"],-command["vmax"],command["vmax"]),
30 | 's' : cmd_num_func(command,"vx",-command["step"],-command["vmax"],command["vmax"]),
31 | 'a' : cmd_num_func(command,"vw", command["step"],-command["vmax"],command["vmax"]),
32 | 'd' : cmd_num_func(command,"vw",-command["step"],-command["vmax"],command["vmax"]),
33 | Key.space : cmd_reset_func(command)
34 | }
35 |
36 | class Publisher:
37 | def __init__(self):
38 | self.vel_pub = rospy.Publisher(
39 | '/course_agv/velocity',
40 | geometry_msgs.msg.Twist, queue_size=1)
41 | self.cmd = geometry_msgs.msg.Twist()
42 |
43 | def pub(self,command):
44 | if rospy.is_shutdown():
45 | exit()
46 | print("publish command : vx - %.2f vw - %.2f"%(command['vx'],command['vw']))
47 | self.cmd.linear.x = command["vx"]
48 | self.cmd.angular.z = command["vw"]
49 | self.vel_pub.publish(self.cmd)
50 |
51 | def press_function(map_table,publisher):
52 | def on_press(key):
53 | global NEED_EXIT
54 | if key == Key.esc:
55 | NEED_EXIT = True
56 | return False
57 | try:
58 | convert_key = key.char
59 | except AttributeError:
60 | convert_key = key
61 | # print('{0} pressed'.format(convert_key))
62 | if convert_key in map_table:
63 | map_table[convert_key]()
64 | publisher.pub(command)
65 | else:
66 | print('\n{0} not in table'.format(convert_key))
67 | return on_press
68 |
69 | def main():
70 | node_name = "velocity_publisher"
71 | print("node : ",node_name)
72 | rospy.init_node(node_name,anonymous=True)
73 | publisher = Publisher()
74 | with Listener(on_press=press_function(KEY_MAP_TABLE,publisher)) as listener:
75 | listener.join()
76 |
77 | if __name__ == '__main__':
78 | main()
79 |
--------------------------------------------------------------------------------
/gazebo/course_agv_control/scripts/kinematics.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import rospy
4 | import geometry_msgs.msg
5 | from std_msgs.msg import Float64
6 |
7 | class Kinematics:
8 | left_wheel_vel = 0.0
9 | right_wheel_vel = 0.0
10 | def __init__(self):
11 | # call rospy.Subscriber() and rospy.Publisher() to define receiver and publisher
12 | # type: geometry_msgs.msg.Twist, Float64, Float64
13 | self.publ = rospy.Publisher('/course_agv/left_wheel_velocity_controller/command', Float64, queue_size=10)
14 | self.pubr = rospy.Publisher('/course_agv/right_wheel_velocity_controller/command', Float64, queue_size=10)
15 | # self.subs = rospy.Subscriber('course_agv/velocity', geometry_msgs.msg.Twist, self.callback)
16 | # input:
17 | # data:
18 | # (data.linear.x, data.angular.z)
19 | # call self.kinematics(vx, vw) to compute wheel velocities
20 | def callback(self, data):
21 | # Compute self.left_wheel_vel and self.right_wheel_vel according to input
22 | self.kinematics(data.linear.x,data.angular.z)
23 | self.publish()
24 |
25 | # input: vx and vw of the robot
26 | # output: wheel velocities of two wheels
27 | def kinematics(self,vx,vw):
28 | # too simple method , TODO
29 | print(vx,vw)
30 | self.left_wheel_vel = (vx - (0.08/3+0.1)*vw)/0.08
31 | self.right_wheel_vel = (vx + (0.08/3+0.1)*vw)/0.08
32 |
33 | # Call publisher to publish wheel velocities
34 | def publish(self):
35 | self.publ.publish(self.left_wheel_vel)
36 | self.pubr.publish(self.right_wheel_vel)
37 | # print(self.left_wheel_vel,self.right_wheel_vel)
38 |
39 | def main():
40 | node_name = "course_agv_kinematics"
41 | print("node : ",node_name)
42 |
43 | try:
44 | rospy.init_node(node_name)
45 | k = Kinematics()
46 | rate = rospy.Rate(rospy.get_param('~publish_rate',200))
47 | while not rospy.is_shutdown():
48 | k.publish()
49 | rospy.Subscriber('/course_agv/velocity', geometry_msgs.msg.Twist, k.callback)
50 | rospy.spin()
51 | rate.sleep()
52 | except rospy.ROSInterruptException:
53 | pass
54 |
55 | if __name__ == '__main__':
56 | main()
57 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(course_agv_description)
3 |
4 | ## Compile as C++11, supported in ROS Kinetic and newer
5 | # add_compile_options(-std=c++11)
6 |
7 | ## Find catkin macros and libraries
8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
9 | ## is used, also find other catkin packages
10 | find_package(catkin REQUIRED)
11 |
12 | ## System dependencies are found with CMake's conventions
13 | # find_package(Boost REQUIRED COMPONENTS system)
14 |
15 |
16 | ## Uncomment this if the package has a setup.py. This macro ensures
17 | ## modules and global scripts declared therein get installed
18 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
19 | # catkin_python_setup()
20 |
21 | ################################################
22 | ## Declare ROS messages, services and actions ##
23 | ################################################
24 |
25 | ## To declare and build messages, services or actions from within this
26 | ## package, follow these steps:
27 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in
28 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
29 | ## * In the file package.xml:
30 | ## * add a build_depend tag for "message_generation"
31 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
32 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
33 | ## but can be declared for certainty nonetheless:
34 | ## * add a exec_depend tag for "message_runtime"
35 | ## * In this file (CMakeLists.txt):
36 | ## * add "message_generation" and every package in MSG_DEP_SET to
37 | ## find_package(catkin REQUIRED COMPONENTS ...)
38 | ## * add "message_runtime" and every package in MSG_DEP_SET to
39 | ## catkin_package(CATKIN_DEPENDS ...)
40 | ## * uncomment the add_*_files sections below as needed
41 | ## and list every .msg/.srv/.action file to be processed
42 | ## * uncomment the generate_messages entry below
43 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
44 |
45 | ## Generate messages in the 'msg' folder
46 | # add_message_files(
47 | # FILES
48 | # Message1.msg
49 | # Message2.msg
50 | # )
51 |
52 | ## Generate services in the 'srv' folder
53 | # add_service_files(
54 | # FILES
55 | # Service1.srv
56 | # Service2.srv
57 | # )
58 |
59 | ## Generate actions in the 'action' folder
60 | # add_action_files(
61 | # FILES
62 | # Action1.action
63 | # Action2.action
64 | # )
65 |
66 | ## Generate added messages and services with any dependencies listed here
67 | # generate_messages(
68 | # DEPENDENCIES
69 | # std_msgs # Or other packages containing msgs
70 | # )
71 |
72 | ################################################
73 | ## Declare ROS dynamic reconfigure parameters ##
74 | ################################################
75 |
76 | ## To declare and build dynamic reconfigure parameters within this
77 | ## package, follow these steps:
78 | ## * In the file package.xml:
79 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
80 | ## * In this file (CMakeLists.txt):
81 | ## * add "dynamic_reconfigure" to
82 | ## find_package(catkin REQUIRED COMPONENTS ...)
83 | ## * uncomment the "generate_dynamic_reconfigure_options" section below
84 | ## and list every .cfg file to be processed
85 |
86 | ## Generate dynamic reconfigure parameters in the 'cfg' folder
87 | # generate_dynamic_reconfigure_options(
88 | # cfg/DynReconf1.cfg
89 | # cfg/DynReconf2.cfg
90 | # )
91 |
92 | ###################################
93 | ## catkin specific configuration ##
94 | ###################################
95 | ## The catkin_package macro generates cmake config files for your package
96 | ## Declare things to be passed to dependent projects
97 | ## INCLUDE_DIRS: uncomment this if your package contains header files
98 | ## LIBRARIES: libraries you create in this project that dependent projects also need
99 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need
100 | ## DEPENDS: system dependencies of this project that dependent projects also need
101 | catkin_package(
102 | # INCLUDE_DIRS include
103 | # LIBRARIES course_agv_description
104 | # CATKIN_DEPENDS other_catkin_pkg
105 | # DEPENDS system_lib
106 | )
107 |
108 | ###########
109 | ## Build ##
110 | ###########
111 |
112 | ## Specify additional locations of header files
113 | ## Your package locations should be listed before other locations
114 | include_directories(
115 | # include
116 | # ${catkin_INCLUDE_DIRS}
117 | )
118 |
119 | ## Declare a C++ library
120 | # add_library(${PROJECT_NAME}
121 | # src/${PROJECT_NAME}/course_agv_description.cpp
122 | # )
123 |
124 | ## Add cmake target dependencies of the library
125 | ## as an example, code may need to be generated before libraries
126 | ## either from message generation or dynamic reconfigure
127 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
128 |
129 | ## Declare a C++ executable
130 | ## With catkin_make all packages are built within a single CMake context
131 | ## The recommended prefix ensures that target names across packages don't collide
132 | # add_executable(${PROJECT_NAME}_node src/course_agv_description_node.cpp)
133 |
134 | ## Rename C++ executable without prefix
135 | ## The above recommended prefix causes long target names, the following renames the
136 | ## target back to the shorter version for ease of user use
137 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
138 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
139 |
140 | ## Add cmake target dependencies of the executable
141 | ## same as for the library above
142 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
143 |
144 | ## Specify libraries to link a library or executable target against
145 | # target_link_libraries(${PROJECT_NAME}_node
146 | # ${catkin_LIBRARIES}
147 | # )
148 |
149 | #############
150 | ## Install ##
151 | #############
152 |
153 | # all install targets should use catkin DESTINATION variables
154 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
155 |
156 | ## Mark executable scripts (Python etc.) for installation
157 | ## in contrast to setup.py, you can choose the destination
158 | # install(PROGRAMS
159 | # scripts/my_python_script
160 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
161 | # )
162 |
163 | ## Mark executables for installation
164 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
165 | # install(TARGETS ${PROJECT_NAME}_node
166 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
167 | # )
168 |
169 | ## Mark libraries for installation
170 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
171 | # install(TARGETS ${PROJECT_NAME}
172 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
173 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
174 | # RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
175 | # )
176 |
177 | ## Mark cpp header files for installation
178 | # install(DIRECTORY include/${PROJECT_NAME}/
179 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
180 | # FILES_MATCHING PATTERN "*.h"
181 | # PATTERN ".svn" EXCLUDE
182 | # )
183 |
184 | ## Mark other files for installation (e.g. launch and bag files, etc.)
185 | # install(FILES
186 | # # myfile1
187 | # # myfile2
188 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
189 | # )
190 |
191 | #############
192 | ## Testing ##
193 | #############
194 |
195 | ## Add gtest based cpp test target and link libraries
196 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_course_agv_description.cpp)
197 | # if(TARGET ${PROJECT_NAME}-test)
198 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
199 | # endif()
200 |
201 | ## Add folders to be run by python nosetests
202 | # catkin_add_nosetests(test)
203 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/launch/course_agv.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 78
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded:
7 | - /Global Options1
8 | - /Status1
9 | - /RobotModel1
10 | Splitter Ratio: 0.5
11 | Tree Height: 549
12 | - Class: rviz/Selection
13 | Name: Selection
14 | - Class: rviz/Tool Properties
15 | Expanded:
16 | - /2D Pose Estimate1
17 | - /2D Nav Goal1
18 | - /Publish Point1
19 | Name: Tool Properties
20 | Splitter Ratio: 0.5886790156364441
21 | - Class: rviz/Views
22 | Expanded:
23 | - /Current View1
24 | Name: Views
25 | Splitter Ratio: 0.5
26 | - Class: rviz/Time
27 | Experimental: false
28 | Name: Time
29 | SyncMode: 0
30 | SyncSource: ""
31 | Preferences:
32 | PromptSaveOnExit: true
33 | Toolbars:
34 | toolButtonStyle: 2
35 | Visualization Manager:
36 | Class: ""
37 | Displays:
38 | - Alpha: 0.5
39 | Cell Size: 1
40 | Class: rviz/Grid
41 | Color: 160; 160; 164
42 | Enabled: true
43 | Line Style:
44 | Line Width: 0.029999999329447746
45 | Value: Lines
46 | Name: Grid
47 | Normal Cell Count: 0
48 | Offset:
49 | X: 0
50 | Y: 0
51 | Z: 0
52 | Plane: XY
53 | Plane Cell Count: 10
54 | Reference Frame:
55 | Value: true
56 | - Alpha: 1
57 | Class: rviz/RobotModel
58 | Collision Enabled: false
59 | Enabled: true
60 | Links:
61 | All Links Enabled: true
62 | Expand Joint Details: false
63 | Expand Link Details: false
64 | Expand Tree: false
65 | Link Tree Style: Links in Alphabetic Order
66 | course_agv__left_wheel:
67 | Alpha: 1
68 | Show Axes: false
69 | Show Trail: false
70 | Value: true
71 | course_agv__right_wheel:
72 | Alpha: 1
73 | Show Axes: false
74 | Show Trail: false
75 | Value: true
76 | robot_base:
77 | Alpha: 1
78 | Show Axes: false
79 | Show Trail: false
80 | robot_chassis:
81 | Alpha: 1
82 | Show Axes: false
83 | Show Trail: false
84 | Value: true
85 | Name: RobotModel
86 | Robot Description: robot_description
87 | TF Prefix: ""
88 | Update Interval: 0
89 | Value: true
90 | Visual Enabled: true
91 | - Class: rviz/TF
92 | Enabled: true
93 | Frame Timeout: 15
94 | Frames:
95 | All Enabled: true
96 | course_agv__left_wheel:
97 | Value: true
98 | course_agv__right_wheel:
99 | Value: true
100 | robot_base:
101 | Value: true
102 | robot_chassis:
103 | Value: true
104 | Marker Scale: 1
105 | Name: TF
106 | Show Arrows: true
107 | Show Axes: true
108 | Show Names: true
109 | Tree:
110 | robot_base:
111 | course_agv__left_wheel:
112 | {}
113 | course_agv__right_wheel:
114 | {}
115 | robot_chassis:
116 | {}
117 | Update Interval: 0
118 | Value: true
119 | Enabled: true
120 | Global Options:
121 | Background Color: 48; 48; 48
122 | Default Light: true
123 | Fixed Frame: robot_base
124 | Frame Rate: 30
125 | Name: root
126 | Tools:
127 | - Class: rviz/Interact
128 | Hide Inactive Objects: true
129 | - Class: rviz/MoveCamera
130 | - Class: rviz/Select
131 | - Class: rviz/FocusCamera
132 | - Class: rviz/Measure
133 | - Class: rviz/SetInitialPose
134 | Theta std deviation: 0.2617993950843811
135 | Topic: /initialpose
136 | X std deviation: 0.5
137 | Y std deviation: 0.5
138 | - Class: rviz/SetGoal
139 | Topic: /move_base_simple/goal
140 | - Class: rviz/PublishPoint
141 | Single click: true
142 | Topic: /clicked_point
143 | Value: true
144 | Views:
145 | Current:
146 | Class: rviz/Orbit
147 | Distance: 2.859943151473999
148 | Enable Stereo Rendering:
149 | Stereo Eye Separation: 0.05999999865889549
150 | Stereo Focal Distance: 1
151 | Swap Stereo Eyes: false
152 | Value: false
153 | Focal Point:
154 | X: 0
155 | Y: 0
156 | Z: 0
157 | Focal Shape Fixed Size: true
158 | Focal Shape Size: 0.05000000074505806
159 | Invert Z Axis: false
160 | Name: Current View
161 | Near Clip Distance: 0.009999999776482582
162 | Pitch: 0.785398006439209
163 | Target Frame:
164 | Value: Orbit (rviz)
165 | Yaw: 0.785398006439209
166 | Saved: ~
167 | Window Geometry:
168 | Displays:
169 | collapsed: false
170 | Height: 846
171 | Hide Left Dock: false
172 | Hide Right Dock: false
173 | QMainWindow State: 000000ff00000000fd000000040000000000000156000002b0fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002b0000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002b0fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002b0000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004b00000003efc0100000002fb0000000800540069006d00650100000000000004b0000002eb00fffffffb0000000800540069006d006501000000000000045000000000000000000000023f000002b000000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
174 | Selection:
175 | collapsed: false
176 | Time:
177 | collapsed: false
178 | Tool Properties:
179 | collapsed: false
180 | Views:
181 | collapsed: false
182 | Width: 1200
183 | X: 60
184 | Y: 27
185 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/launch/course_agv_rviz.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | course_agv_description
4 | 0.0.0
5 | The course_agv_description package
6 |
7 |
8 |
9 |
10 | zjunlict
11 |
12 |
13 |
14 |
15 |
16 | TODO
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | catkin
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/urdf/course_agv.gazebo:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | /course_agv
8 | gazebo_ros_control/DefaultRobotHWSim
9 |
10 |
11 |
12 |
24 |
25 |
26 | 0.0
27 | 0.0
28 | Gazebo/DarkYellow
29 |
30 |
31 |
32 |
33 | 0
34 | 0
35 | 1.0
36 | 1.0
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 1
49 | 1
50 | 0
51 | 0
52 |
53 |
54 |
55 |
56 | Gazebo/DarkGrey
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | 1
65 | 1
66 | 0
67 | 0
68 |
69 |
70 |
71 |
72 | Gazebo/DarkGrey
73 |
74 |
75 |
76 |
77 |
78 | 0 0 0 0 0 0
79 | true
80 | 5
81 |
82 |
83 |
84 | 200
85 | 1
86 | -3.14159
87 | 3.14159
88 |
89 |
90 |
91 | 0.10
92 | 20.0
93 | 0.05
94 |
95 |
96 | gaussian
97 |
101 | 0.0
102 | 0.01
103 |
104 |
105 |
106 | /course_agv/laser/scan
107 | course_agv__hokuyo__link
108 |
109 |
110 |
111 |
112 |
113 |
114 | true
115 | Gazebo/Red
116 |
117 | true
118 | 100
119 | true
120 | __default_topic__
121 |
122 | /course_agv/imu
123 | imu_link
124 | 10.0
125 | 0.0
126 | 0 0 0
127 | 0 0 0
128 | course_agv__imu
129 |
130 | 0 0 0 0 0 0
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/urdf/course_agv.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 | transmission_interface/SimpleTransmission
200 |
201 | hardware_interface/VelocityJointInterface
202 |
203 |
204 | hardware_interface/VelocityJointInterface
205 | 1
206 |
207 |
208 |
209 |
210 | transmission_interface/SimpleTransmission
211 |
212 | hardware_interface/VelocityJointInterface
213 |
214 |
215 | hardware_interface/VelocityJointInterface
216 | 1
217 |
218 |
219 |
220 |
--------------------------------------------------------------------------------
/gazebo/course_agv_description/urdf/materials.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(course_agv_gazebo)
3 |
4 | ## Compile as C++11, supported in ROS Kinetic and newer
5 | # add_compile_options(-std=c++11)
6 |
7 | ## Find catkin macros and libraries
8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
9 | ## is used, also find other catkin packages
10 | find_package(catkin REQUIRED)
11 |
12 | ## System dependencies are found with CMake's conventions
13 | # find_package(Boost REQUIRED COMPONENTS system)
14 |
15 |
16 | ## Uncomment this if the package has a setup.py. This macro ensures
17 | ## modules and global scripts declared therein get installed
18 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
19 | # catkin_python_setup()
20 |
21 | ################################################
22 | ## Declare ROS messages, services and actions ##
23 | ################################################
24 |
25 | ## To declare and build messages, services or actions from within this
26 | ## package, follow these steps:
27 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in
28 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
29 | ## * In the file package.xml:
30 | ## * add a build_depend tag for "message_generation"
31 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
32 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
33 | ## but can be declared for certainty nonetheless:
34 | ## * add a exec_depend tag for "message_runtime"
35 | ## * In this file (CMakeLists.txt):
36 | ## * add "message_generation" and every package in MSG_DEP_SET to
37 | ## find_package(catkin REQUIRED COMPONENTS ...)
38 | ## * add "message_runtime" and every package in MSG_DEP_SET to
39 | ## catkin_package(CATKIN_DEPENDS ...)
40 | ## * uncomment the add_*_files sections below as needed
41 | ## and list every .msg/.srv/.action file to be processed
42 | ## * uncomment the generate_messages entry below
43 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
44 |
45 | ## Generate messages in the 'msg' folder
46 | # add_message_files(
47 | # FILES
48 | # Message1.msg
49 | # Message2.msg
50 | # )
51 |
52 | ## Generate services in the 'srv' folder
53 | # add_service_files(
54 | # FILES
55 | # Service1.srv
56 | # Service2.srv
57 | # )
58 |
59 | ## Generate actions in the 'action' folder
60 | # add_action_files(
61 | # FILES
62 | # Action1.action
63 | # Action2.action
64 | # )
65 |
66 | ## Generate added messages and services with any dependencies listed here
67 | # generate_messages(
68 | # DEPENDENCIES
69 | # std_msgs # Or other packages containing msgs
70 | # )
71 |
72 | ################################################
73 | ## Declare ROS dynamic reconfigure parameters ##
74 | ################################################
75 |
76 | ## To declare and build dynamic reconfigure parameters within this
77 | ## package, follow these steps:
78 | ## * In the file package.xml:
79 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
80 | ## * In this file (CMakeLists.txt):
81 | ## * add "dynamic_reconfigure" to
82 | ## find_package(catkin REQUIRED COMPONENTS ...)
83 | ## * uncomment the "generate_dynamic_reconfigure_options" section below
84 | ## and list every .cfg file to be processed
85 |
86 | ## Generate dynamic reconfigure parameters in the 'cfg' folder
87 | # generate_dynamic_reconfigure_options(
88 | # cfg/DynReconf1.cfg
89 | # cfg/DynReconf2.cfg
90 | # )
91 |
92 | ###################################
93 | ## catkin specific configuration ##
94 | ###################################
95 | ## The catkin_package macro generates cmake config files for your package
96 | ## Declare things to be passed to dependent projects
97 | ## INCLUDE_DIRS: uncomment this if your package contains header files
98 | ## LIBRARIES: libraries you create in this project that dependent projects also need
99 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need
100 | ## DEPENDS: system dependencies of this project that dependent projects also need
101 | catkin_package(
102 | # INCLUDE_DIRS include
103 | # LIBRARIES course_agv_gazebo
104 | # CATKIN_DEPENDS other_catkin_pkg
105 | # DEPENDS system_lib
106 | )
107 |
108 | ###########
109 | ## Build ##
110 | ###########
111 |
112 | ## Specify additional locations of header files
113 | ## Your package locations should be listed before other locations
114 | include_directories(
115 | # include
116 | # ${catkin_INCLUDE_DIRS}
117 | )
118 |
119 | ## Declare a C++ library
120 | # add_library(${PROJECT_NAME}
121 | # src/${PROJECT_NAME}/course_agv_gazebo.cpp
122 | # )
123 |
124 | ## Add cmake target dependencies of the library
125 | ## as an example, code may need to be generated before libraries
126 | ## either from message generation or dynamic reconfigure
127 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
128 |
129 | ## Declare a C++ executable
130 | ## With catkin_make all packages are built within a single CMake context
131 | ## The recommended prefix ensures that target names across packages don't collide
132 | # add_executable(${PROJECT_NAME}_node src/course_agv_gazebo_node.cpp)
133 |
134 | ## Rename C++ executable without prefix
135 | ## The above recommended prefix causes long target names, the following renames the
136 | ## target back to the shorter version for ease of user use
137 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
138 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
139 |
140 | ## Add cmake target dependencies of the executable
141 | ## same as for the library above
142 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
143 |
144 | ## Specify libraries to link a library or executable target against
145 | # target_link_libraries(${PROJECT_NAME}_node
146 | # ${catkin_LIBRARIES}
147 | # )
148 |
149 | #############
150 | ## Install ##
151 | #############
152 |
153 | # all install targets should use catkin DESTINATION variables
154 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
155 |
156 | ## Mark executable scripts (Python etc.) for installation
157 | ## in contrast to setup.py, you can choose the destination
158 | # install(PROGRAMS
159 | # scripts/my_python_script
160 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
161 | # )
162 |
163 | ## Mark executables for installation
164 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
165 | # install(TARGETS ${PROJECT_NAME}_node
166 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
167 | # )
168 |
169 | ## Mark libraries for installation
170 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
171 | # install(TARGETS ${PROJECT_NAME}
172 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
173 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
174 | # RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
175 | # )
176 |
177 | ## Mark cpp header files for installation
178 | # install(DIRECTORY include/${PROJECT_NAME}/
179 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
180 | # FILES_MATCHING PATTERN "*.h"
181 | # PATTERN ".svn" EXCLUDE
182 | # )
183 |
184 | ## Mark other files for installation (e.g. launch and bag files, etc.)
185 | # install(FILES
186 | # # myfile1
187 | # # myfile2
188 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
189 | # )
190 |
191 | #############
192 | ## Testing ##
193 | #############
194 |
195 | ## Add gtest based cpp test target and link libraries
196 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_course_agv_gazebo.cpp)
197 | # if(TARGET ${PROJECT_NAME}-test)
198 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
199 | # endif()
200 |
201 | ## Add folders to be run by python nosetests
202 | # catkin_add_nosetests(test)
203 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/config/map.yaml:
--------------------------------------------------------------------------------
1 | image: map/map.png
2 | resolution: 0.155
3 | origin: [-10.0, -10.0, 0.0]
4 | occupied_thresh: 0.65
5 | free_thresh: 0.196
6 | negate: 1
7 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/config/map/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friedrich-M/Wheeled-robot-path-planning-algorithm/566230578d03db637da2251d6d82ca3f3d36ec68/gazebo/course_agv_gazebo/config/map/map.png
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/config/map/map_backup2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friedrich-M/Wheeled-robot-path-planning-algorithm/566230578d03db637da2251d6d82ca3f3d36ec68/gazebo/course_agv_gazebo/config/map/map_backup2.png
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/launch/course_agv.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 78
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded:
7 | - /Global Options1
8 | - /Status1
9 | - /Grid1
10 | - /RobotModel1
11 | - /TF1
12 | - /Map1
13 | - /LaserScan1
14 | - /Imu1
15 | Splitter Ratio: 0.5
16 | Tree Height: 695
17 | - Class: rviz/Selection
18 | Name: Selection
19 | - Class: rviz/Tool Properties
20 | Expanded:
21 | - /2D Pose Estimate1
22 | - /2D Nav Goal1
23 | - /Publish Point1
24 | Name: Tool Properties
25 | Splitter Ratio: 0.5886790156364441
26 | - Class: rviz/Views
27 | Expanded:
28 | - /Current View1
29 | Name: Views
30 | Splitter Ratio: 0.5
31 | - Class: rviz/Time
32 | Experimental: false
33 | Name: Time
34 | SyncMode: 0
35 | SyncSource: LaserScan
36 | Preferences:
37 | PromptSaveOnExit: true
38 | Toolbars:
39 | toolButtonStyle: 2
40 | Visualization Manager:
41 | Class: ""
42 | Displays:
43 | - Alpha: 0.5
44 | Cell Size: 1
45 | Class: rviz/Grid
46 | Color: 160; 160; 164
47 | Enabled: true
48 | Line Style:
49 | Line Width: 0.029999999329447746
50 | Value: Lines
51 | Name: Grid
52 | Normal Cell Count: 0
53 | Offset:
54 | X: 0
55 | Y: 0
56 | Z: 0
57 | Plane: XY
58 | Plane Cell Count: 20
59 | Reference Frame:
60 | Value: true
61 | - Alpha: 1
62 | Class: rviz/RobotModel
63 | Collision Enabled: false
64 | Enabled: true
65 | Links:
66 | All Links Enabled: true
67 | Expand Joint Details: false
68 | Expand Link Details: false
69 | Expand Tree: false
70 | Link Tree Style: Links in Alphabetic Order
71 | course_agv__hokuyo__link:
72 | Alpha: 1
73 | Show Axes: false
74 | Show Trail: false
75 | Value: true
76 | course_agv__imu:
77 | Alpha: 1
78 | Show Axes: false
79 | Show Trail: false
80 | Value: true
81 | course_agv__left_wheel:
82 | Alpha: 1
83 | Show Axes: false
84 | Show Trail: false
85 | Value: true
86 | course_agv__right_wheel:
87 | Alpha: 1
88 | Show Axes: false
89 | Show Trail: false
90 | Value: true
91 | robot_base:
92 | Alpha: 1
93 | Show Axes: false
94 | Show Trail: false
95 | robot_chassis:
96 | Alpha: 1
97 | Show Axes: false
98 | Show Trail: false
99 | Value: true
100 | Name: RobotModel
101 | Robot Description: robot_description
102 | TF Prefix: ""
103 | Update Interval: 0
104 | Value: true
105 | Visual Enabled: true
106 | - Class: rviz/TF
107 | Enabled: true
108 | Frame Timeout: 15
109 | Frames:
110 | All Enabled: true
111 | course_agv__hokuyo__link:
112 | Value: true
113 | course_agv__imu:
114 | Value: true
115 | course_agv__left_wheel:
116 | Value: true
117 | course_agv__right_wheel:
118 | Value: true
119 | map:
120 | Value: true
121 | robot_base:
122 | Value: true
123 | robot_chassis:
124 | Value: true
125 | world_base:
126 | Value: true
127 | Marker Scale: 0.30000001192092896
128 | Name: TF
129 | Show Arrows: true
130 | Show Axes: true
131 | Show Names: true
132 | Tree:
133 | world_base:
134 | map:
135 | {}
136 | robot_base:
137 | course_agv__hokuyo__link:
138 | {}
139 | course_agv__imu:
140 | {}
141 | course_agv__left_wheel:
142 | {}
143 | course_agv__right_wheel:
144 | {}
145 | robot_chassis:
146 | {}
147 | Update Interval: 0
148 | Value: true
149 | - Alpha: 0.5
150 | Class: rviz/Map
151 | Color Scheme: map
152 | Draw Behind: false
153 | Enabled: true
154 | Name: Map
155 | Topic: /map
156 | Unreliable: false
157 | Use Timestamp: false
158 | Value: true
159 | - Alpha: 0.6000000238418579
160 | Autocompute Intensity Bounds: true
161 | Autocompute Value Bounds:
162 | Max Value: 10
163 | Min Value: -10
164 | Value: true
165 | Axis: Z
166 | Channel Name: intensity
167 | Class: rviz/LaserScan
168 | Color: 255; 255; 255
169 | Color Transformer: Intensity
170 | Decay Time: 0
171 | Enabled: true
172 | Invert Rainbow: false
173 | Max Color: 255; 255; 255
174 | Max Intensity: 0
175 | Min Color: 0; 0; 0
176 | Min Intensity: 0
177 | Name: LaserScan
178 | Position Transformer: XYZ
179 | Queue Size: 10
180 | Selectable: true
181 | Size (Pixels): 3
182 | Size (m): 0.10000000149011612
183 | Style: Flat Squares
184 | Topic: /course_agv/laser/scan
185 | Unreliable: false
186 | Use Fixed Frame: true
187 | Use rainbow: true
188 | Value: true
189 | - Alpha: 0.20000000298023224
190 | Class: rviz_plugin_tutorials/Imu
191 | Color: 32; 74; 135
192 | Enabled: true
193 | History Length: 1
194 | Name: Imu
195 | Topic: /course_agv/imu
196 | Unreliable: false
197 | Value: true
198 | Enabled: true
199 | Global Options:
200 | Background Color: 85; 87; 83
201 | Default Light: true
202 | Fixed Frame: world_base
203 | Frame Rate: 30
204 | Name: root
205 | Tools:
206 | - Class: rviz/Interact
207 | Hide Inactive Objects: true
208 | - Class: rviz/MoveCamera
209 | - Class: rviz/Select
210 | - Class: rviz/FocusCamera
211 | - Class: rviz/Measure
212 | - Class: rviz/SetInitialPose
213 | Theta std deviation: 0.2617993950843811
214 | Topic: /initialpose
215 | X std deviation: 0.5
216 | Y std deviation: 0.5
217 | - Class: rviz/SetGoal
218 | Topic: /move_base_simple/goal
219 | - Class: rviz/PublishPoint
220 | Single click: true
221 | Topic: /clicked_point
222 | Value: true
223 | Views:
224 | Current:
225 | Class: rviz/Orbit
226 | Distance: 7.358518600463867
227 | Enable Stereo Rendering:
228 | Stereo Eye Separation: 0.05999999865889549
229 | Stereo Focal Distance: 1
230 | Swap Stereo Eyes: false
231 | Value: false
232 | Focal Point:
233 | X: 0
234 | Y: 0
235 | Z: 0
236 | Focal Shape Fixed Size: true
237 | Focal Shape Size: 0.05000000074505806
238 | Invert Z Axis: false
239 | Name: Current View
240 | Near Clip Distance: 0.009999999776482582
241 | Pitch: 0.6803986430168152
242 | Target Frame:
243 | Value: Orbit (rviz)
244 | Yaw: 5.888577461242676
245 | Saved: ~
246 | Window Geometry:
247 | Displays:
248 | collapsed: false
249 | Height: 992
250 | Hide Left Dock: false
251 | Hide Right Dock: false
252 | QMainWindow State: 000000ff00000000fd00000004000000000000015600000342fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d00000342000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000342fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d00000342000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007800000003efc0100000002fb0000000800540069006d0065010000000000000780000002eb00fffffffb0000000800540069006d006501000000000000045000000000000000000000050f0000034200000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
253 | Selection:
254 | collapsed: false
255 | Time:
256 | collapsed: false
257 | Tool Properties:
258 | collapsed: false
259 | Views:
260 | collapsed: false
261 | Width: 1920
262 | X: 0
263 | Y: 27
264 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/launch/course_agv_world.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/launch/course_agv_world_rviz.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/models/ground_plane_for_agv/map/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friedrich-M/Wheeled-robot-path-planning-algorithm/566230578d03db637da2251d6d82ca3f3d36ec68/gazebo/course_agv_gazebo/models/ground_plane_for_agv/map/map.png
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/models/ground_plane_for_agv/map/map_backup2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friedrich-M/Wheeled-robot-path-planning-algorithm/566230578d03db637da2251d6d82ca3f3d36ec68/gazebo/course_agv_gazebo/models/ground_plane_for_agv/map/map_backup2.png
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/models/ground_plane_for_agv/materials/textures/flat_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friedrich-M/Wheeled-robot-path-planning-algorithm/566230578d03db637da2251d6d82ca3f3d36ec68/gazebo/course_agv_gazebo/models/ground_plane_for_agv/materials/textures/flat_normal.png
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/models/ground_plane_for_agv/materials/textures/grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friedrich-M/Wheeled-robot-path-planning-algorithm/566230578d03db637da2251d6d82ca3f3d36ec68/gazebo/course_agv_gazebo/models/ground_plane_for_agv/materials/textures/grey.png
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/models/ground_plane_for_agv/model.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ground Plane AGV
5 | 1.0
6 | model.sdf
7 |
8 |
9 | Mark
10 | hzypp@sina.cn
11 |
12 |
13 |
14 | A simple test ground for AGV.
15 |
16 |
17 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/models/ground_plane_for_agv/model.sdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 |
8 |
9 | model://ground_plane_for_agv/map/map.png
10 | 20 20 0.4
11 | 0 0 0.01
12 |
13 |
14 |
15 |
16 |
17 |
18 | false
19 |
24 |
29 |
30 | model://ground_plane_for_agv/materials/textures/grey.png
31 | model://ground_plane_for_agv/materials/textures/flat_normal.png
32 | 1
33 |
34 |
35 | 2
36 | 5
37 |
38 |
39 | 4
40 | 5
41 |
42 | model://ground_plane_for_agv/map/map.png
43 | 20 20 0.8
44 | 0 0 0.01
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | course_agv_gazebo
4 | 0.0.0
5 | The course_agv_gazebo package
6 |
7 |
8 |
9 |
10 | zjunlict
11 |
12 |
13 |
14 |
15 |
16 | TODO
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | catkin
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/scripts/robot_tf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import rospy
4 | import tf
5 | from gazebo_msgs.msg import LinkStates
6 | from geometry_msgs.msg import Pose
7 | from geometry_msgs.msg import Quaternion
8 |
9 | class GazeboLinkPose:
10 | link_name = ''
11 | link_pose = Pose()
12 |
13 | def __init__(self, robot_name, link_name):
14 | self.robot_name = robot_name
15 | self.link_name = link_name
16 | # self.link_name_rectified = link_name.replace("::", "_")
17 |
18 | if not self.link_name:
19 | raise ValueError("'link_name' is an empty string")
20 |
21 | self.states_sub = rospy.Subscriber(
22 | "/gazebo/link_states", LinkStates, self.callback)
23 | self.pose_pub = rospy.Publisher(
24 | "/gazebo/" + (self.robot_name + '__' + self.link_name), Pose, queue_size=10)
25 | self.tf_pub = tf.TransformBroadcaster()
26 |
27 | def callback(self, data):
28 | try:
29 | ind = data.name.index(self.robot_name + "::" + self.link_name)
30 | self.link_pose = data.pose[ind]
31 | except ValueError:
32 | pass
33 |
34 | def publish_tf(self):
35 | p = self.link_pose.position
36 | o = self.link_pose.orientation
37 | self.tf_pub.sendTransform((p.x,p.y,p.z),(o.x,o.y,o.z,o.w),
38 | rospy.Time.now(),self.link_name,"map")
39 | self.tf_pub.sendTransform((0,0,0),tf.transformations.quaternion_from_euler(0,0,0),
40 | rospy.Time.now(),"world_base","map")
41 |
42 | if __name__ == '__main__':
43 | try:
44 | rospy.init_node('robot_pose_tf_publisher')
45 | gp = GazeboLinkPose(rospy.get_param('~robot_name', 'course_agv'),
46 | rospy.get_param('~link_name', 'robot_base'))
47 | publish_rate = rospy.get_param('~publish_rate', 100)
48 |
49 | rate = rospy.Rate(publish_rate)
50 | while not rospy.is_shutdown():
51 | gp.pose_pub.publish(gp.link_pose)
52 | gp.publish_tf()
53 | rate.sleep()
54 |
55 | except rospy.ROSInterruptException:
56 | pass
57 |
--------------------------------------------------------------------------------
/gazebo/course_agv_gazebo/worlds/course_agv.world:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | model://ground_plane_for_agv
7 |
8 |
9 |
10 |
11 | model://sun
12 |
13 |
14 |
15 |
16 |
17 | 4.927360 -4.376610 3.740080 0.000000 0.275643 2.356190
18 | orbit
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(course_agv_nav)
3 |
4 | ## Compile as C++11, supported in ROS Kinetic and newer
5 | # add_compile_options(-std=c++11)
6 |
7 | ## Find catkin macros and libraries
8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
9 | ## is used, also find other catkin packages
10 | find_package(catkin REQUIRED COMPONENTS
11 | rospy
12 | std_msgs
13 | message_generation
14 | )
15 | ## System dependencies are found with CMake's conventions
16 | # find_package(Boost REQUIRED COMPONENTS system)
17 |
18 |
19 | ## Uncomment this if the package has a setup.py. This macro ensures
20 | ## modules and global scripts declared therein get installed
21 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
22 | # catkin_python_setup()
23 |
24 | ################################################
25 | ## Declare ROS messages, services and actions ##
26 | ################################################
27 |
28 | ## To declare and build messages, services or actions from within this
29 | ## package, follow these steps:
30 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in
31 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
32 | ## * In the file package.xml:
33 | ## * add a build_depend tag for "message_generation"
34 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
35 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
36 | ## but can be declared for certainty nonetheless:
37 | ## * add a exec_depend tag for "message_runtime"
38 | ## * In this file (CMakeLists.txt):
39 | ## * add "message_generation" and every package in MSG_DEP_SET to
40 | ## find_package(catkin REQUIRED COMPONENTS ...)
41 | ## * add "message_runtime" and every package in MSG_DEP_SET to
42 | ## catkin_package(CATKIN_DEPENDS ...)
43 | ## * uncomment the add_*_files sections below as needed
44 | ## and list every .msg/.srv/.action file to be processed
45 | ## * uncomment the generate_messages entry below
46 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
47 |
48 | ## Generate messages in the 'msg' folder
49 | # add_message_files(
50 | # FILES
51 | # Message1.msg
52 | # Message2.msg
53 | # )
54 |
55 | ## Generate services in the 'srv' folder
56 | add_service_files(
57 | FILES
58 | Plan.srv
59 | # Service1.srv
60 | # Service2.srv
61 | )
62 |
63 | ## Generate actions in the 'action' folder
64 | # add_action_files(
65 | # FILES
66 | # Action1.action
67 | # Action2.action
68 | # )
69 |
70 | ## Generate added messages and services with any dependencies listed here
71 | generate_messages(
72 | DEPENDENCIES
73 | std_msgs # Or other packages containing msgs
74 | )
75 |
76 | ################################################
77 | ## Declare ROS dynamic reconfigure parameters ##
78 | ################################################
79 |
80 | ## To declare and build dynamic reconfigure parameters within this
81 | ## package, follow these steps:
82 | ## * In the file package.xml:
83 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
84 | ## * In this file (CMakeLists.txt):
85 | ## * add "dynamic_reconfigure" to
86 | ## find_package(catkin REQUIRED COMPONENTS ...)
87 | ## * uncomment the "generate_dynamic_reconfigure_options" section below
88 | ## and list every .cfg file to be processed
89 |
90 | ## Generate dynamic reconfigure parameters in the 'cfg' folder
91 | # generate_dynamic_reconfigure_options(
92 | # cfg/DynReconf1.cfg
93 | # cfg/DynReconf2.cfg
94 | # )
95 |
96 | ###################################
97 | ## catkin specific configuration ##
98 | ###################################
99 | ## The catkin_package macro generates cmake config files for your package
100 | ## Declare things to be passed to dependent projects
101 | ## INCLUDE_DIRS: uncomment this if your package contains header files
102 | ## LIBRARIES: libraries you create in this project that dependent projects also need
103 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need
104 | ## DEPENDS: system dependencies of this project that dependent projects also need
105 | catkin_package(
106 | # INCLUDE_DIRS include
107 | # LIBRARIES course_agv_nav
108 | CATKIN_DEPENDS message_runtime
109 | # DEPENDS system_lib
110 | )
111 |
112 | ###########
113 | ## Build ##
114 | ###########
115 |
116 | ## Specify additional locations of header files
117 | ## Your package locations should be listed before other locations
118 | include_directories(
119 | # include
120 | # ${catkin_INCLUDE_DIRS}
121 | )
122 |
123 | ## Declare a C++ library
124 | # add_library(${PROJECT_NAME}
125 | # src/${PROJECT_NAME}/course_agv_nav.cpp
126 | # )
127 |
128 | ## Add cmake target dependencies of the library
129 | ## as an example, code may need to be generated before libraries
130 | ## either from message generation or dynamic reconfigure
131 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
132 |
133 | ## Declare a C++ executable
134 | ## With catkin_make all packages are built within a single CMake context
135 | ## The recommended prefix ensures that target names across packages don't collide
136 | # add_executable(${PROJECT_NAME}_node src/course_agv_nav_node.cpp)
137 |
138 | ## Rename C++ executable without prefix
139 | ## The above recommended prefix causes long target names, the following renames the
140 | ## target back to the shorter version for ease of user use
141 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
142 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
143 |
144 | ## Add cmake target dependencies of the executable
145 | ## same as for the library above
146 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
147 |
148 | ## Specify libraries to link a library or executable target against
149 | # target_link_libraries(${PROJECT_NAME}_node
150 | # ${catkin_LIBRARIES}
151 | # )
152 |
153 | #############
154 | ## Install ##
155 | #############
156 |
157 | # all install targets should use catkin DESTINATION variables
158 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
159 |
160 | ## Mark executable scripts (Python etc.) for installation
161 | ## in contrast to setup.py, you can choose the destination
162 | # install(PROGRAMS
163 | # scripts/my_python_script
164 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
165 | # )
166 |
167 | ## Mark executables for installation
168 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
169 | # install(TARGETS ${PROJECT_NAME}_node
170 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
171 | # )
172 |
173 | ## Mark libraries for installation
174 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
175 | # install(TARGETS ${PROJECT_NAME}
176 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
177 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
178 | # RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
179 | # )
180 |
181 | ## Mark cpp header files for installation
182 | # install(DIRECTORY include/${PROJECT_NAME}/
183 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
184 | # FILES_MATCHING PATTERN "*.h"
185 | # PATTERN ".svn" EXCLUDE
186 | # )
187 |
188 | ## Mark other files for installation (e.g. launch and bag files, etc.)
189 | # install(FILES
190 | # # myfile1
191 | # # myfile2
192 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
193 | # )
194 |
195 | #############
196 | ## Testing ##
197 | #############
198 |
199 | ## Add gtest based cpp test target and link libraries
200 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_course_agv_nav.cpp)
201 | # if(TARGET ${PROJECT_NAME}-test)
202 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
203 | # endif()
204 |
205 | ## Add folders to be run by python nosetests
206 | # catkin_add_nosetests(test)
207 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/launch/nav.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/launch/nav.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 78
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded:
7 | - /Global Options1
8 | - /Status1
9 | - /RobotModel1
10 | - /Path1
11 | - /Goal1
12 | - /Mid Goal1
13 | - /Odometry1
14 | - /Map2
15 | Splitter Ratio: 0.5
16 | Tree Height: 719
17 | - Class: rviz/Selection
18 | Name: Selection
19 | - Class: rviz/Tool Properties
20 | Expanded:
21 | - /2D Pose Estimate1
22 | - /2D Nav Goal1
23 | - /Publish Point1
24 | Name: Tool Properties
25 | Splitter Ratio: 0.5886790156364441
26 | - Class: rviz/Views
27 | Expanded:
28 | - /Current View1
29 | Name: Views
30 | Splitter Ratio: 0.5
31 | - Class: rviz/Time
32 | Experimental: false
33 | Name: Time
34 | SyncMode: 0
35 | SyncSource: LaserScan
36 | Preferences:
37 | PromptSaveOnExit: true
38 | Toolbars:
39 | toolButtonStyle: 2
40 | Visualization Manager:
41 | Class: ""
42 | Displays:
43 | - Alpha: 0.5
44 | Cell Size: 1
45 | Class: rviz/Grid
46 | Color: 160; 160; 164
47 | Enabled: true
48 | Line Style:
49 | Line Width: 0.029999999329447746
50 | Value: Lines
51 | Name: Grid
52 | Normal Cell Count: 0
53 | Offset:
54 | X: 0
55 | Y: 0
56 | Z: 0
57 | Plane: XY
58 | Plane Cell Count: 20
59 | Reference Frame:
60 | Value: true
61 | - Alpha: 0.699999988079071
62 | Class: rviz/Map
63 | Color Scheme: map
64 | Draw Behind: false
65 | Enabled: false
66 | Name: Map
67 | Topic: /map
68 | Unreliable: false
69 | Use Timestamp: false
70 | Value: false
71 | - Alpha: 0.699999988079071
72 | Class: rviz/RobotModel
73 | Collision Enabled: false
74 | Enabled: true
75 | Links:
76 | All Links Enabled: true
77 | Expand Joint Details: false
78 | Expand Link Details: false
79 | Expand Tree: false
80 | Link Tree Style: Links in Alphabetic Order
81 | course_agv__hokuyo__link:
82 | Alpha: 1
83 | Show Axes: false
84 | Show Trail: false
85 | Value: true
86 | course_agv__imu:
87 | Alpha: 1
88 | Show Axes: false
89 | Show Trail: false
90 | Value: true
91 | course_agv__left_wheel:
92 | Alpha: 1
93 | Show Axes: false
94 | Show Trail: false
95 | Value: true
96 | course_agv__right_wheel:
97 | Alpha: 1
98 | Show Axes: false
99 | Show Trail: false
100 | Value: true
101 | robot_base:
102 | Alpha: 1
103 | Show Axes: false
104 | Show Trail: false
105 | robot_chassis:
106 | Alpha: 1
107 | Show Axes: false
108 | Show Trail: false
109 | Value: true
110 | Name: RobotModel
111 | Robot Description: robot_description
112 | TF Prefix: ""
113 | Update Interval: 0
114 | Value: true
115 | Visual Enabled: true
116 | - Alpha: 0.6000000238418579
117 | Autocompute Intensity Bounds: true
118 | Autocompute Value Bounds:
119 | Max Value: 10
120 | Min Value: -10
121 | Value: true
122 | Axis: Z
123 | Channel Name: intensity
124 | Class: rviz/LaserScan
125 | Color: 255; 255; 255
126 | Color Transformer: Intensity
127 | Decay Time: 0
128 | Enabled: true
129 | Invert Rainbow: false
130 | Max Color: 255; 255; 255
131 | Min Color: 0; 0; 0
132 | Name: LaserScan
133 | Position Transformer: XYZ
134 | Queue Size: 10
135 | Selectable: true
136 | Size (Pixels): 3
137 | Size (m): 0.05000000074505806
138 | Style: Flat Squares
139 | Topic: /course_agv/laser/scan
140 | Unreliable: false
141 | Use Fixed Frame: true
142 | Use rainbow: true
143 | Value: true
144 | - Alpha: 1
145 | Buffer Length: 1
146 | Class: rviz/Path
147 | Color: 237; 212; 0
148 | Enabled: true
149 | Head Diameter: 0.15000000596046448
150 | Head Length: 0.10000000149011612
151 | Length: 0.30000001192092896
152 | Line Style: Lines
153 | Line Width: 0.029999999329447746
154 | Name: Path
155 | Offset:
156 | X: 0
157 | Y: 0
158 | Z: 0
159 | Pose Color: 255; 85; 255
160 | Pose Style: None
161 | Queue Size: 10
162 | Radius: 0.029999999329447746
163 | Shaft Diameter: 0.05000000074505806
164 | Shaft Length: 0.10000000149011612
165 | Topic: /course_agv/global_path
166 | Unreliable: false
167 | Value: true
168 | - Alpha: 1
169 | Axes Length: 1
170 | Axes Radius: 0.10000000149011612
171 | Class: rviz/Pose
172 | Color: 117; 80; 123
173 | Enabled: true
174 | Head Length: 0.30000001192092896
175 | Head Radius: 0.10000000149011612
176 | Name: Goal
177 | Queue Size: 10
178 | Shaft Length: 1
179 | Shaft Radius: 0.05000000074505806
180 | Shape: Arrow
181 | Topic: /course_agv/goal
182 | Unreliable: false
183 | Value: true
184 | - Alpha: 1
185 | Axes Length: 0.20000000298023224
186 | Axes Radius: 0.10000000149011612
187 | Class: rviz/Pose
188 | Color: 255; 25; 0
189 | Enabled: true
190 | Head Length: 0.30000001192092896
191 | Head Radius: 0.10000000149011612
192 | Name: Mid Goal
193 | Queue Size: 10
194 | Shaft Length: 1
195 | Shaft Radius: 0.05000000074505806
196 | Shape: Axes
197 | Topic: /course_agv/mid_goal
198 | Unreliable: false
199 | Value: true
200 | - Angle Tolerance: 0.10000000149011612
201 | Class: rviz/Odometry
202 | Covariance:
203 | Orientation:
204 | Alpha: 0.5
205 | Color: 255; 255; 127
206 | Color Style: Unique
207 | Frame: Local
208 | Offset: 1
209 | Scale: 1
210 | Value: true
211 | Position:
212 | Alpha: 0.30000001192092896
213 | Color: 204; 51; 204
214 | Scale: 1
215 | Value: true
216 | Value: true
217 | Enabled: true
218 | Keep: 100
219 | Name: Odometry
220 | Position Tolerance: 0.10000000149011612
221 | Queue Size: 10
222 | Shape:
223 | Alpha: 1
224 | Axes Length: 1
225 | Axes Radius: 0.10000000149011612
226 | Color: 255; 25; 0
227 | Head Length: 0.30000001192092896
228 | Head Radius: 0.10000000149011612
229 | Shaft Length: 1
230 | Shaft Radius: 0.05000000074505806
231 | Value: Arrow
232 | Topic: /icp_odom
233 | Unreliable: false
234 | Value: true
235 | - Alpha: 0.699999988079071
236 | Class: rviz/Map
237 | Color Scheme: map
238 | Draw Behind: false
239 | Enabled: true
240 | Name: Map
241 | Topic: /map
242 | Unreliable: false
243 | Use Timestamp: false
244 | Value: true
245 | - Alpha: 1
246 | Arrow Length: 0.30000001192092896
247 | Axes Length: 0.30000001192092896
248 | Axes Radius: 0.009999999776482582
249 | Class: rviz/PoseArray
250 | Color: 255; 25; 0
251 | Enabled: true
252 | Head Length: 0.07000000029802322
253 | Head Radius: 0.029999999329447746
254 | Name: PoseArray
255 | Queue Size: 10
256 | Shaft Length: 0.23000000417232513
257 | Shaft Radius: 0.009999999776482582
258 | Shape: Arrow (Flat)
259 | Topic: /test/obs
260 | Unreliable: false
261 | Value: true
262 | Enabled: true
263 | Global Options:
264 | Background Color: 48; 48; 48
265 | Default Light: true
266 | Fixed Frame: map
267 | Frame Rate: 30
268 | Name: root
269 | Tools:
270 | - Class: rviz/Interact
271 | Hide Inactive Objects: true
272 | - Class: rviz/MoveCamera
273 | - Class: rviz/Select
274 | - Class: rviz/FocusCamera
275 | - Class: rviz/Measure
276 | - Class: rviz/SetInitialPose
277 | Theta std deviation: 0.2617993950843811
278 | Topic: /initialpose
279 | X std deviation: 0.5
280 | Y std deviation: 0.5
281 | - Class: rviz/SetGoal
282 | Topic: /course_agv/goal
283 | - Class: rviz/PublishPoint
284 | Single click: true
285 | Topic: /clicked_point
286 | Value: true
287 | Views:
288 | Current:
289 | Class: rviz/Orbit
290 | Distance: 18.78539276123047
291 | Enable Stereo Rendering:
292 | Stereo Eye Separation: 0.05999999865889549
293 | Stereo Focal Distance: 1
294 | Swap Stereo Eyes: false
295 | Value: false
296 | Field of View: 0.7853981852531433
297 | Focal Point:
298 | X: 0.8559381365776062
299 | Y: -1.2515515089035034
300 | Z: -0.07588538527488708
301 | Focal Shape Fixed Size: true
302 | Focal Shape Size: 0.05000000074505806
303 | Invert Z Axis: false
304 | Name: Current View
305 | Near Clip Distance: 0.009999999776482582
306 | Pitch: 1.0353978872299194
307 | Target Frame:
308 | Yaw: 0.6653981804847717
309 | Saved: ~
310 | Window Geometry:
311 | Displays:
312 | collapsed: false
313 | Height: 1016
314 | Hide Left Dock: false
315 | Hide Right Dock: false
316 | QMainWindow State: 000000ff00000000fd00000004000000000000015f0000035afc0200000007fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d0000035a000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f0000035afc0200000004fb0000001e0054006f006f006c002000500072006f0070006500720074006900650073010000003d0000035a0000005c00fffffffb0000001e0054006f006f006c002000500072006f0070006500720074006900650073010000003d000002b00000000000000000fb0000000a0056006900650077007300000000ec00000201000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007280000003efc0100000002fb0000000800540069006d0065010000000000000728000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000004ae0000035a00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
317 | Selection:
318 | collapsed: false
319 | Time:
320 | collapsed: false
321 | Tool Properties:
322 | collapsed: false
323 | Views:
324 | collapsed: false
325 | Width: 1832
326 | X: 88
327 | Y: 27
328 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | course_agv_nav
4 | 0.0.0
5 | The course_agv_nav package
6 |
7 |
8 |
9 |
10 | zjunlict
11 |
12 |
13 |
14 |
15 |
16 | TODO
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | message_generation
43 |
44 |
45 |
46 | message_runtime
47 |
48 |
49 |
50 |
51 | catkin
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/scripts/A_star.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import numpy as np
3 | import math as m
4 |
5 |
6 | class A_star:
7 | """A*算法类
8 |
9 | 通过A*算法求解二维栅格地图中指定起点、终点的最短路径序列
10 |
11 | Attributes:
12 | closed: 类型:list,已经探索过且封闭的顶点
13 | unknown:类型:list. 未探索过的顶点
14 | now: 类型:Vertex,当前所处顶点
15 | start_point: 类型:Point,起点
16 | end_point: 类型:Point 终点
17 | map: 类型:array 栅格地图信息
18 | end_Vertex: 类型:Vertex 终点所对应的顶点
19 | max_iter: 类型:int 算法的最大迭代次数,超过此次数终止计算
20 | Vertex: 定义一个顶点类(class),用于描述图中的顶点
21 |
22 | """
23 |
24 | def __init__(self,obstacles_point, start_point, end_point, planning_minx,planning_miny,planning_maxx,planning_maxy,grid,dist):
25 | """"由给定起点、终点以及地图初始化A*的数据"""
26 | self.closed = [] # 封闭的顶点
27 | self.unknown = [] # 未探索过的顶点
28 | self.now = 0 # 现在的Vertex
29 | self.start_point = (int((start_point[0]-planning_minx)/grid),int((start_point[1]-planning_miny)/grid))
30 | self.end_point = (int((end_point[0]-planning_minx)/grid),int((end_point[1]-planning_miny)/grid))
31 | self.end_Vertex = self.Vertex(self.end_point, self.end_point, m.inf)
32 | self.max_iter = 50000
33 | self.grid = grid
34 | self.dist = dist
35 | self.planning_minx = planning_minx
36 | self.planning_miny = planning_miny
37 | self.planning_maxx = planning_maxx
38 | self.planning_maxy = planning_maxy
39 | self.width = int((planning_maxx - planning_minx)/grid+1)
40 | self.height = int((planning_maxy - planning_miny)/grid+1)
41 | self.map = np.empty([self.height, self.width], dtype=float)
42 | for i in range(self.height):
43 | for j in range(self.width):
44 | self.temp=np.hypot(obstacles_point[:,0]-(i*grid+planning_minx),obstacles_point[:,1]-(j*grid+planning_miny))
45 | self.map[i,j] = min(self.temp)
46 | if self.map[i,j] > dist:
47 | self.map[i,j] = 0
48 | else:
49 | self.map[i,j] = 1
50 |
51 | class Vertex:
52 | """ 图中顶点类
53 |
54 | 将栅格地图中的坐标点抽象为“图”中的顶点,储存更多信息,便于实现A*
55 |
56 | Attributes:
57 | point: 类型:Point 当前顶点所对应的坐标点
58 | endpoint: 类型: Point 终点坐标(本质上和上面的end_point一致,这里定义成类内变量更加方便后续的编程
59 | father: 类型:Vertex 类似一个指针,指向自己的上一个顶点,用于回溯
60 | g:类型:float A*算法中的g(n)函数值,表示现有已知代价
61 | h: 类型:float A*算法中的h(n)函数值,表示对当前节点的未来代价的评估
62 | f: 类型:float g(n)函数 + f(n)函数,用来评估该节点的总代价
63 | """
64 |
65 | def __init__(self, point, endpoint, g):
66 | """"使用给定坐标、终点坐标、已得g值进行初始化"""
67 | self.point = point # 自己坐标
68 | self.endpoint = endpoint # 终点坐标
69 | self.father = None # 父节点,用来回溯最短路
70 | self.g = g # 现有代价g值,是由起点到该点的累加值
71 | self.h =m.hypot((point[0]-endpoint[0]),(point[1]-endpoint[1]))
72 | self.f = self.g + self.h
73 |
74 | def search_next(self, vertical, horizontal):
75 | """搜寻并确定下一个可到达的顶点Vertex
76 |
77 | 通过传入的水平位移dx - horizontal和竖直位移dy-vertical来确定下一个可到达的顶点
78 |
79 | Args:
80 | self: Vertex类所有变量均已知,包括当前坐标self.point
81 | vertical: 类型:int 表示竖直方向的坐标增量 dy
82 | horizontal: 类型:int 表示水平方向坐标增量 dx
83 |
84 | return:
85 | nearVertex: 类型:Vertex 下一个可探索的顶点
86 | """
87 | nextpoint =(self.point[0] + horizontal,
88 | self.point[1] + vertical)
89 | if vertical != 0 and horizontal != 0: # 走斜对角线,g值增加根号2
90 | nearVertex = A_star.Vertex(
91 | nextpoint, self.endpoint, self.g + 1.414)
92 | else: # 走十字方向,g值增加1
93 | nearVertex = A_star.Vertex(
94 | nextpoint, self.endpoint, self.g + 1)
95 | return nearVertex
96 |
97 | def Process(self):
98 | """A*算法核心函数,整个算法的流程控制
99 |
100 | 每次从未探索区域中找到f(n)最小的顶点,并进行探索和回溯
101 | 最终得到终点的顶点end_Vertex,通过father指针逆向索引得到最优路径
102 |
103 | Args:
104 | self: A_star类所有变量均已知
105 |
106 | return:
107 | self.closed : 类型:list 列表中的每个元素为Vertex, 是所有曾探索过的点
108 | best_path: 类型:list 列表中的每个元素为Vertex,是从起点到终点的路径序列顶点集
109 | """
110 | start_Vertex = self.Vertex(self.start_point, self.end_point, 0)
111 | self.unknown.append(start_Vertex)
112 | arrive = 0
113 | count = 0
114 | while arrive != 1 and count < self.max_iter: # arrive = 1时到达终点
115 | self.now = self.min_cost_Vertex() # 每次从unknown中选取一个f(n)最小的Vertex
116 | self.closed.append(self.now) # 起点不计入
117 | arrive = self.explore_next(self.now) # 对选中的Vertex进行周边探索
118 | count += 1
119 | best_path_X = []
120 | best_path_Y = []
121 | temp_Vertex = self.end_Vertex # 拿到终点顶点
122 | # while (temp_Vertex.point[0] != self.start_plloint[0] or temp_Vertex.point[1] != self.start_point[1]):
123 | while (temp_Vertex):
124 | best_path_X.append(temp_Vertex.point[0])
125 | best_path_Y.append(temp_Vertex.point[1])
126 | temp_Vertex = temp_Vertex.father
127 | best_path_X.reverse() # 逆转链表
128 | best_path_Y.reverse() # 逆转链表
129 | best_path_X=[float(i)*self.grid+self.planning_minx for i in best_path_X]
130 | best_path_Y=[float(i)*self.grid+self.planning_miny for i in best_path_Y]
131 | # print(best_path_X,best_path_Y)
132 | return best_path_X,best_path_Y
133 |
134 | def min_cost_Vertex(self):
135 | """在unknown list中找到最小f(n)的顶点
136 | 将该顶点从unknown list中移除并添加到closed list中
137 |
138 | Args:
139 | self: A_star类所有变量均已知
140 |
141 | return:
142 | Vertex_min: 类型:Vertex unknown顶点集中f(n)最小的顶点
143 | """
144 | Vertex_min = self.unknown[0]
145 | for Vertex_temp in self.unknown:
146 | if Vertex_temp.f < Vertex_min.f:
147 | Vertex_min = Vertex_temp
148 | self.unknown.remove(Vertex_min)
149 | return Vertex_min
150 |
151 | def is_unknown(self, Vertex):
152 | """判断顶点是否在未探索区域
153 |
154 | 如果改顶点属于为探索区域,则返回未更新过的顶点
155 |
156 | Args:
157 | self: A_star类所有变量均已知
158 | Vertex: 类型:Vertex 待判断的顶点
159 |
160 | return:
161 | 0: 表示不属于未探索区域
162 | Vertex_temp:unknown列表中未更新的Vertex
163 | """
164 | for Vertex_temp in self.unknown:
165 | if Vertex_temp.point == Vertex.point:
166 | return Vertex_temp
167 | return 0
168 |
169 | def is_closed(self, Vertex):
170 | """判断顶点是否在已探索区域
171 |
172 | Args:
173 | self: A_star类所有变量均已知
174 | Vertex: 类型:Vertex 待判断的顶点
175 |
176 | return:
177 | 0/1: 1表示该顶点属于已探索区域,0表示不属于
178 | """
179 | for closeVertex_temp in self.closed:
180 | if closeVertex_temp.point[0] == Vertex.point[0] and closeVertex_temp.point[1] == Vertex.point[1]:
181 | return 1
182 | return 0
183 |
184 | def is_obstacle(self, Vertex):
185 | """判断顶点是否位于障碍物区域
186 |
187 | Args:
188 | self: A_star类所有变量均已知
189 | Vertex: 类型:Vertex 待判断的顶点
190 |
191 | return:
192 | 0/1: 1表示该顶点位于障碍物区域,0表示不位于
193 | """
194 | if self.map[Vertex.point[0]][Vertex.point[1]] == 1:
195 | return 1
196 | return 0
197 |
198 | def explore_next(self, Vertex):
199 | """探索下一个顶点
200 |
201 | 栅格地图中可以探索的有8个方向,可以用vertical和horizontal的循环表示
202 | 相应地更新unknown序列,可有配合Vertex类中的函数search_next来实现
203 |
204 | 注意事项:如果探索到的节点已经处于unknown list中,那么需要对比一下原有的f值
205 | 与当前的f值,选取最小f值的保存到unknown list中
206 |
207 | Args:
208 | self: A_star类所有变量均已知
209 | Vertex: 类型:Vertex 当前所在的顶点
210 |
211 | return:
212 | 0:表示还未探索到终点
213 | 1:表示已经探索到终点,A*即将结束
214 | """
215 | num = {-1, 0, 1}
216 | for vertical in num:
217 | for horizontal in num:
218 | if vertical == 0 and horizontal == 0:
219 | continue
220 | if Vertex.point[0] + horizontal < 0:
221 | continue
222 | if Vertex.point[0] + horizontal >= self.width:
223 | continue
224 | if Vertex.point[1] + vertical < 0:
225 | continue
226 | if Vertex.point[1] + vertical >= self.height:
227 | continue
228 | Vertex_next = Vertex.search_next(vertical, horizontal)
229 | if Vertex_next.point[0] == self.end_point[0] and Vertex_next.point[1] == self.end_point[1]:
230 | Vertex_next.father = Vertex
231 | self.end_Vertex = Vertex_next
232 | return 1
233 | if self.is_closed(Vertex_next):
234 | continue
235 | if self.is_obstacle(Vertex_next):
236 | continue
237 | if self.is_unknown(Vertex_next) == 0:
238 | Vertex_next.father = Vertex
239 | self.unknown.append(Vertex_next)
240 | else:
241 | Vertex_old = self.is_unknown(Vertex_next)
242 | if Vertex_next.f < Vertex_old.f:
243 | self.unknown.remove(Vertex_old)
244 | Vertex_next.father = Vertex
245 | self.unknown.append(Vertex_next)
246 | return 0
247 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/scripts/RRT_plan.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from cmath import inf
3 | import numpy as np
4 | import math as m
5 |
6 |
7 |
8 | class RRT:
9 | """RRT算法类
10 |
11 | Attributes:
12 | known:类型:Tree. 探索过的顶点
13 | start_point: 类型:Point,起点
14 | end_point: 类型:Point 终点
15 | start_node: 类型:Tree 起点所对应的顶点
16 | Vertex: 定义一个顶点类(class),用于描述图中的顶点
17 |
18 | """
19 |
20 | def __init__(self,obstacles_point, start_point, end_point, planning_minx,planning_miny,planning_maxx,planning_maxy,grid,dist):
21 | """"由给定起点、终点初始化"""
22 | self.node_set = []
23 | self.start_point = start_point
24 | self.end_point = end_point
25 | self.start_node = self.RRT_Tree(start_point,[],[],end_point,start_point)
26 | self.planning_minx = planning_minx
27 | self.planning_miny = planning_miny
28 | self.planning_maxx = planning_maxx
29 | self.planning_maxy = planning_maxy
30 | self.obstacles_point = obstacles_point
31 | self.grid = grid
32 | self.dist = dist
33 |
34 | class RRT_Tree:
35 | """RRT树
36 |
37 | Attributes:
38 | point 当前节点的坐标
39 | father 父节点
40 | child 子节点
41 | """
42 | def __init__(self,point,father,child,endpoint,startpoint):
43 | self.point = point
44 | self.father = father
45 | self.child = child
46 | self.endpoint = endpoint # 终点坐标
47 | self.startpoint = startpoint # 起点坐标
48 |
49 |
50 | def Process(self):
51 | """RRT算法核心函数,整个算法的流程控制
52 |
53 | 通过发散找点,最终到终点附近的时候进行回溯
54 |
55 | Args:
56 | self: RRT类所有变量均已知
57 |
58 | return:
59 | best_path_X:最有路径的x坐标
60 | best_path_Y:最有路径的y坐标
61 | """
62 | new_node = self.start_node
63 | self.node_set.append(new_node)
64 | while self.if_nearend(new_node) == 0:
65 | new_node = self.search_next()
66 | self.node_set.append(new_node)
67 | end_node = self.RRT_Tree(self.end_point,new_node,[],self.end_point,self.start_point)
68 | best_path_X = []
69 | best_path_Y = []
70 | temp_node = end_node # 拿到终点顶点
71 | while (temp_node):
72 | best_path_X.append(temp_node.point[0])
73 | best_path_Y.append(temp_node.point[1])
74 | temp_node = temp_node.father
75 | best_path_X.reverse() # 逆转链表
76 | best_path_Y.reverse() # 逆转链表
77 | return best_path_X,best_path_Y
78 | def search_next(self):
79 | """搜寻并确定下一个可到达的顶点near_node
80 |
81 | Args:
82 | self: RRT_Tree类所有变量均已知,包括当前坐标self.point
83 |
84 | return:
85 | near_node: 类型:Tree 下一个可探索的顶点
86 | """
87 | flag =1
88 | while flag:
89 | flag = 0
90 | # 利用rand()函数在[0,1]区间内随机生成一个数
91 | if np.random.rand() < self.grid:
92 | # 如果小于0.5,则在图 img_binary 的范围内随机采样一个点
93 | x_temp = np.random.randint(self.planning_minx,self.planning_maxx, dtype=int)
94 | y_temp = np.random.randint(self.planning_miny,self.planning_maxy, dtype=int)
95 | temp_point = (x_temp,y_temp)
96 | else:
97 | # 否则用目标点作为采样点
98 | temp_point = self.end_point
99 | dist,nearest_node = self.min_distance_node(temp_point)
100 | d = ([temp_point[i]-nearest_node.point[i] for i in range(len(temp_point))])/np.linalg.norm([temp_point[i]-nearest_node.point[i] for i in range(len(temp_point))])
101 | near_node = RRT.RRT_Tree(nearest_node.point+d*self.grid,nearest_node,[],nearest_node.endpoint,nearest_node.startpoint)
102 | for obstacles_point in self.obstacles_point:
103 | if np.linalg.norm(obstacles_point-near_node.point)node.value+self.grid:
108 | near_node.father = node
109 | if near_node.value+self.grid np.sqrt((robot_info[0]-midpos[0])**2+(robot_info[1]-midpos[1])**2):
90 | return [0,0]#,best_traj,all_traj,all_u
91 | # time.sleep(1)
92 | # 遍历
93 | tot = 100000.0
94 | tot_info=robot_info
95 | cost = np.zeros((possibleV_num, possibleW_num))
96 | for vw in possibleW:
97 | for vx in possibleV:
98 | traj = []
99 | robot_info_temp = [robot_info[0], robot_info[1], robot_info[2], vx, vw]
100 | robot_info_temp = self.motion(robot_info_temp, dwaconfig)
101 | # 计算cost
102 | cost1 = self.heading_cost(robot_info_temp[0], robot_info_temp[1], midpos[0], midpos[1], robot_info_temp)
103 | cost2 = self.dist_cost(dwaconfig, midpos,robot_info_temp, planning_obs, 0.1)
104 | cost3 = self.velocity_cost(robot_info_temp[3], dwaconfig.max_speed)
105 | cost = cost1 * dwaconfig.to_goal_cost_gain + cost2 * dwaconfig.obstacle_cost_gain + cost3 * dwaconfig.speed_cost_gain
106 | # print(vx, vw, cost1, cost2, cost3, cost)
107 | if(cost < tot):
108 | tot = cost
109 | nvx = vx
110 | nvw = vw
111 | tot_info = robot_info_temp
112 | where = robot_info_temp
113 | for i in range(int(dwaconfig.predict_time / dwaconfig.dt)):
114 | where = self.motion(where, dwaconfig)
115 | traj.append([where[0],where[1]])
116 | all_traj.append(traj)
117 | all_u.append(cost)
118 | where = tot_info
119 | for i in range(int(dwaconfig.predict_time / dwaconfig.dt)):
120 | where = self.motion(where, dwaconfig)
121 | best_traj.append([where[0],where[1]])
122 | best_traj = np.array(best_traj)
123 | all_traj = np.array(all_traj)
124 | return [nvx, nvw]#,best_traj,all_traj,all_u
125 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/scripts/global_planner.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import rospy
3 | import tf
4 | from nav_msgs.srv import GetMap
5 | from nav_msgs.msg import Path
6 | from geometry_msgs.msg import PoseStamped
7 | from course_agv_nav.srv import Plan,PlanResponse
8 | from nav_msgs.msg import OccupancyGrid
9 | from std_msgs.msg import Bool
10 | import numpy as np
11 | import matplotlib.pyplot as plt
12 | import A_star as A
13 |
14 | class GlobalPlanner:
15 | def __init__(self):
16 | self.plan_sx = 0.0
17 | self.plan_sy = 0.0
18 | self.plan_gx = 8.0
19 | self.plan_gy = -8.0
20 | self.plan_grid_size = 0.3
21 | self.plan_robot_radius = 0.6
22 | self.plan_ox = []
23 | self.plan_oy = []
24 | self.plan_rx = []
25 | self.plan_ry = []
26 |
27 | # count to update map
28 | self.map_count = 0
29 |
30 | self.tf = tf.TransformListener()
31 | self.goal_sub = rospy.Subscriber('/course_agv/goal',PoseStamped,self.goalCallback)
32 | self.plan_srv = rospy.Service('/course_agv/global_plan',Plan,self.replan)
33 | self.path_pub = rospy.Publisher('/course_agv/global_path',Path,queue_size = 1)
34 | self.map_sub = rospy.Subscriber('/slam_map',OccupancyGrid,self.mapCallback)
35 | self.collision_sub = rospy.Subscriber('/collision_checker_result',Bool,self.collisionCallback)
36 |
37 | self.updateMap()
38 | # self.updateGlobalPose()
39 |
40 | pass
41 | def goalCallback(self,msg):
42 | self.plan_goal = msg
43 | self.plan_gx = msg.pose.position.x
44 | self.plan_gy = msg.pose.position.y
45 | # print("get new goal!!! ",self.plan_goal)
46 | self.replan(0)
47 | pass
48 |
49 | def collisionCallback(self,msg):
50 | self.replan(0)
51 | def updateGlobalPose(self):
52 | try:
53 | self.tf.waitForTransform("/map", "/robot_base", rospy.Time(), rospy.Duration(4.0))
54 | (self.trans,self.rot) = self.tf.lookupTransform('/map','/robot_base',rospy.Time(0))
55 | except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
56 | print("get tf error!")
57 | self.plan_sx = self.trans[0]
58 | self.plan_sy = self.trans[1]
59 |
60 | def replan(self,req):
61 | print('get request for replan!!!!!!!!')
62 | self.initAStar()
63 | self.updateGlobalPose()
64 | self.plan_rx,self.plan_ry = self.planner.Process()
65 | # self.plan_rx,self.plan_ry = self.a_star.planning(self.plan_ox,self.plan_oy,self.plan_sx,self.plan_sy,self.plan_gx,self.plan_gy,np.array(self.plan_ox).min(),np.array(self.plan_oy).min(),np.array(self.plan_ox).max(),np.array(self.plan_oy).max())
66 | self.publishPath()
67 | res = True
68 | return PlanResponse(res)
69 | def initAStar(self):
70 | map_data = np.array(self.map.data).reshape((-1,self.map.info.height)).transpose()
71 | ox,oy = np.nonzero(map_data > 50)#大于50是障碍物
72 | self.plan_ox = (ox*self.map.info.resolution+self.map.info.origin.position.x).tolist()
73 | self.plan_oy = (oy*self.map.info.resolution+self.map.info.origin.position.y).tolist()
74 | obs = np.stack((self.plan_ox,self.plan_oy),axis=1)
75 | self.planner = A.A_star(obs,[self.plan_sx,self.plan_sy],[self.plan_gx,self.plan_gy],np.array(self.plan_ox).min(),np.array(self.plan_oy).min(),np.array(self.plan_ox).max(),np.array(self.plan_oy).max(),self.plan_grid_size,self.plan_robot_radius)
76 | # self.a_star = AStarPlanner(self.plan_grid_size,self.plan_robot_radius)
77 |
78 | def mapCallback(self,msg):
79 | self.map = msg
80 | pass
81 | def updateMap(self):
82 | rospy.wait_for_service('/static_map')
83 | try:
84 | getMap = rospy.ServiceProxy('/static_map',GetMap)
85 | msg = getMap().map
86 | except:
87 | e = sys.exc_info()[0]
88 | print('Service call failed: %s'%e)
89 | # Update for planning algorithm
90 | self.mapCallback(msg)
91 |
92 | def publishPath(self):
93 | path = Path()
94 | path.header.seq = 0
95 | path.header.stamp = rospy.Time(0)
96 | path.header.frame_id = 'map'
97 | for i in range(len(self.plan_rx)):
98 | pose = PoseStamped()
99 | pose.header.seq = i
100 | pose.header.stamp = rospy.Time(0)
101 | pose.header.frame_id = 'map'
102 | pose.pose.position.x = self.plan_rx[i]#reverse
103 | pose.pose.position.y = self.plan_ry[i]#reverse
104 | pose.pose.position.z = 0.01
105 | pose.pose.orientation.x = 0
106 | pose.pose.orientation.y = 0
107 | pose.pose.orientation.z = 0
108 | pose.pose.orientation.w = 1
109 | path.poses.append(pose)
110 | self.path_pub.publish(path)
111 |
112 |
113 | def main():
114 | rospy.init_node('global_planner')
115 | gp = GlobalPlanner()
116 | rospy.spin()
117 | pass
118 |
119 | if __name__ == '__main__':
120 | main()
121 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/scripts/local_planner.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | import math
4 | import numpy as np
5 | import rospy
6 | import tf
7 | from nav_msgs.srv import GetMap
8 | from nav_msgs.msg import Path
9 | from geometry_msgs.msg import PoseStamped,Twist,PoseArray,Pose
10 | from sensor_msgs.msg import LaserScan
11 |
12 |
13 | import dwaplanner
14 |
15 | from threading import Lock,Thread
16 | import time
17 |
18 | def limitVal(minV,maxV,v):
19 | if v < minV:
20 | return minV
21 | if v > maxV:
22 | return maxV
23 | return v
24 |
25 | class LocalPlanner:
26 | def __init__(self):
27 | self.arrive = 0.1
28 | self.x = 0.0
29 | self.y = 0.0
30 | self.yaw = 0.0
31 | self.vx = 0.0
32 | self.vw = 0.0
33 | self.test_seq_count = 0
34 | # init plan_config for once
35 | self.laser_lock = Lock()
36 | self.plan_config = dwaplanner.Config(0.3)#0.1550000011920929
37 | c = self.plan_config
38 | self.threshold = c.max_speed*c.predict_time
39 |
40 | self.path = Path()
41 | self.tf = tf.TransformListener()
42 | self.path_sub = rospy.Subscriber('/course_agv/global_path',Path,self.pathCallback)
43 | self.vel_pub = rospy.Publisher('/course_agv/velocity',Twist, queue_size=1)
44 | self.midpose_pub = rospy.Publisher('/course_agv/mid_goal',PoseStamped,queue_size=1)
45 | self.laser_sub = rospy.Subscriber('/course_agv/laser/scan',LaserScan,self.laserCallback)
46 | self.obs_pub = rospy.Publisher('/test/obs',PoseArray, queue_size=1)
47 | self.planner_thread = None
48 |
49 | self.need_exit = False
50 |
51 | self.updateMap()
52 | pass
53 |
54 | def updateMap(self):
55 | rospy.wait_for_service('/static_map')
56 | try:
57 | getMap = rospy.ServiceProxy('/static_map',GetMap)
58 | msg = getMap().map
59 | except:
60 | e = sys.exc_info()[0]
61 | print('Service call failed: %s'%e)
62 | # Update for planning algorithm
63 | self.mapCallback(msg)
64 |
65 | def mapCallback(self,msg):
66 | self.map = msg
67 | pass
68 |
69 | def updateGlobalPose(self):
70 | try:
71 | self.tf.waitForTransform("/map", "/robot_base", rospy.Time(), rospy.Duration(4.0))
72 | (self.trans,self.rot) = self.tf.lookupTransform('/map','/robot_base',rospy.Time(0))
73 | except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
74 | print("get tf error!")
75 | euler = tf.transformations.euler_from_quaternion(self.rot)
76 | roll,pitch,yaw = euler[0],euler[1],euler[2]
77 | self.x = self.trans[0]
78 | self.y = self.trans[1]
79 | self.yaw = yaw
80 | ind = self.goal_index
81 | self.goal_index = len(self.path.poses)-1
82 | while ind < len(self.path.poses):
83 | p = self.path.poses[ind].pose.position
84 | dis = math.hypot(p.x-self.x,p.y-self.y)
85 | # print('mdgb;; ',len(self.path.poses),ind,dis)
86 | self.goal_index = ind
87 | if dis > self.threshold:
88 | break
89 | ind += 1
90 | goal = self.path.poses[self.goal_index]
91 | self.midpose_pub.publish(goal)
92 | lgoal = self.tf.transformPose("/robot_base", goal)
93 | self.plan_goal = np.array([lgoal.pose.position.x,lgoal.pose.position.y])
94 | self.goal_dis = math.hypot(self.x-self.path.poses[-1].pose.position.x,self.y-self.path.poses[-1].pose.position.y)
95 |
96 | def laserCallback(self,msg):
97 | # print("get laser msg!!!!",msg)
98 | self.laser_lock.acquire()
99 | # preprocess
100 | self.ob = [[100,100]]
101 | angle_min = msg.angle_min
102 | angle_increment = msg.angle_increment
103 | for i in range(len(msg.ranges)):
104 | a = angle_min + angle_increment*i
105 | r = msg.ranges[i]
106 | if r < self.threshold:
107 | self.ob.append([math.cos(a)*r,math.sin(a)*r])
108 | self.laser_lock.release()
109 | pass
110 |
111 | def calculate(self):
112 | map_data = np.array(self.map.data).reshape((-1,self.map.info.height)).transpose()
113 | ox,oy = np.nonzero(map_data > 50)#大于50是障碍物
114 | self.plan_ox = (ox*self.map.info.resolution+self.map.info.origin.position.x).tolist()
115 | self.plan_oy = (oy*self.map.info.resolution+self.map.info.origin.position.y).tolist()
116 | th = np.ones(len(self.plan_ox))
117 | obs = np.stack((self.plan_ox,self.plan_oy,th),axis=1)
118 | th = self.yaw
119 | R = np.array([[math.cos(th), math.sin(th), -self.x*math.cos(th)-self.y*math.sin(th)],[-math.sin(th), math.cos(th), self.x*math.sin(th)-self.y*math.cos(th)],[0,0,1]])
120 | now_obs = []
121 | for i in range(len(self.plan_ox)):
122 | now_obs.extend((np.matmul(R,np.transpose(obs[i,:]))))
123 | now_obs = np.array(now_obs)
124 | now_obs=now_obs.reshape(len(self.plan_ox),3)
125 | return now_obs[:,0:2]
126 |
127 | def updateObstacle(self):
128 | self.laser_lock.acquire()
129 | self.plan_ob = []
130 | self.plan_ob = np.array(self.ob)
131 | # self.plan_ob = self.calculate()
132 | # print(self.plan_ob)
133 | self.laser_lock.release()
134 | pass
135 | def pathCallback(self,msg):
136 | self.need_exit = True
137 | time.sleep(0.1)
138 | self.path = msg
139 | self.planner_thread = Thread(target=self.planThreadFunc)
140 | self.initPlanning()
141 | self.planner_thread.start()
142 |
143 | def initPlanning(self):
144 | self.goal_index = 0
145 | self.vx = 0.0
146 | self.vw = 0.0
147 | self.dis = 99999
148 | self.updateGlobalPose()
149 | cx = []
150 | cy = []
151 | for pose in self.path.poses:
152 | cx.append(pose.pose.position.x)
153 | cy.append(pose.pose.position.y)
154 | self.goal = np.array([cx[0],cy[0]])
155 | self.plan_cx,self.plan_cy = np.array(cx),np.array(cy)
156 | self.plan_goal = np.array([cx[-1],cy[-1]])
157 | self.plan_x = np.array([0.0,0.0,0.0,self.vx,self.vw])
158 | pass
159 | def planThreadFunc(self):
160 | print("running planning thread!!")
161 | self.need_exit = False
162 | while not self.need_exit:
163 | self.planOnce()
164 | self.publishTestObs(None)
165 | if self.goal_dis < self.arrive:
166 | print("arrive goal!")
167 | break
168 | time.sleep(0.001)
169 | print("exit planning thread!!")
170 | self.publishVel(True)
171 | self.planner_thread = None
172 | pass
173 | def planOnce(self):
174 | self.updateGlobalPose()
175 | # Update plan_x [x(m), y(m), yaw(rad), v(m/s), omega(rad/s)]
176 | self.plan_x = [0.0,0.0,0.0,self.vx,self.vw]
177 | # Update obstacle
178 | self.updateObstacle()
179 | cal = dwaplanner.DWA()
180 | u= cal.plan(self.plan_x,self.plan_config,self.plan_goal,self.plan_ob)
181 | # print(u)
182 | alpha = 0.5
183 | self.vx = u[0]*alpha+self.vx*(1-alpha)
184 | self.vw = u[1]*alpha+self.vw*(1-alpha)
185 | # print(self.vx,self.vw)
186 | # print("mdbg; ",u)
187 | self.publishVel()
188 | pass
189 | def publishTestObs(self,obs):
190 | test_obs = PoseArray()
191 | test_obs.header.seq = self.test_seq_count
192 | test_obs.header.frame_id = "robot_base"
193 | test_obs.header.stamp = rospy.Time(0)
194 |
195 | for i in self.plan_ob:
196 | pose = Pose()
197 | pose.position.x = i[0]
198 | pose.position.y = i[1]
199 | pose.position.z = 0.01
200 | pose.orientation.x = 0
201 | pose.orientation.y = 0
202 | pose.orientation.z = 0
203 | pose.orientation.w = 1
204 | test_obs.poses.append(pose)
205 |
206 | self.obs_pub.publish(test_obs)
207 |
208 | self.test_seq_count += 1
209 |
210 | def publishVel(self,zero = False):
211 | if zero:
212 | self.vx = 0
213 | self.vw = 0
214 | cmd = Twist()
215 | cmd.linear.x = self.vx
216 | cmd.angular.z = self.vw
217 | self.vel_pub.publish(cmd)
218 |
219 | def main():
220 | rospy.init_node('path_Planning')
221 | lp = LocalPlanner()
222 | rospy.spin()
223 | pass
224 |
225 | if __name__ == '__main__':
226 | main()
227 |
--------------------------------------------------------------------------------
/gazebo/course_agv_nav/srv/Plan.srv:
--------------------------------------------------------------------------------
1 | ---
2 | bool res
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import threading
2 | import time
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | from AStarPlanner import AStarPlanner
7 | # from Astar import AStarPlanner
8 |
9 | ## TODO
10 | # from planner import AStarPlanner,RRTPlanner
11 |
12 | plt.rcParams["figure.figsize"] = [8.0,8.0]
13 | plt.rcParams["figure.autolayout"] = True
14 | plt.rcParams['keymap.save'].remove('s')
15 |
16 | class Playground:
17 | def __init__(self,planner=None):
18 | self.dt = 0.2
19 |
20 | self.fig, self.ax = plt.subplots()
21 |
22 | self.fig.canvas.mpl_connect('button_press_event', self.on_mousepress)
23 | self.fig.canvas.mpl_connect('key_press_event', self.on_press)
24 | self.fig.canvas.mpl_connect('motion_notify_event',self.on_mousemove)
25 | self.NEED_EXIT = False
26 |
27 | ############################################
28 |
29 | self.planning_minx = -10
30 | self.planning_miny = -10
31 | self.planning_maxx = 10
32 | self.planning_maxy = 10
33 |
34 | self.planning_obs = np.empty(shape=(0,2))
35 | self.planning_obs_radius = 1.5
36 | self.planning_path = np.empty(shape=(0,2))
37 |
38 | self.planning_start = np.array([0.0,0.0])
39 | self.planning_target = None
40 |
41 | self.planner = planner
42 |
43 | #####################################
44 | self.temp_obs = [0,0]
45 |
46 | def run(self):
47 | while True:
48 | if self.NEED_EXIT:
49 | plt.close("all")
50 | break
51 | plt.cla()
52 | self.__draw()
53 |
54 | def add_obs(self,x,y):
55 | self.planning_obs = np.append(self.planning_obs,[[x,y]],axis=0)
56 | def add_obss(self,xs,ys):
57 | self.planning_obs = np.append(self.planning_obs,np.vstack([xs,ys]).T,axis=0)
58 | def __draw(self):
59 | assert(self.planning_path.shape[1]==2,"the shape of planning path should be '[x,2]', please check your algorithm.")
60 | assert(self.planning_obs.shape[1]==2,"the shape of self.planning_obs(obstacles) should be '[x,2]', please check your algorithm.")
61 |
62 | self.ax.plot(self.planning_start[0],self.planning_start[1],"k>",markersize=12)
63 | if self.planning_target is not None:
64 | self.ax.plot(self.planning_target[0],self.planning_target[1],"r*",markersize=20)
65 |
66 | self.ax.plot(self.planning_path[:,0], self.planning_path[:,1], 'b--')
67 | for obs in self.planning_obs:
68 | self.ax.add_artist(plt.Circle((obs[0],obs[1]), self.planning_obs_radius,fill=False))
69 |
70 | self.ax.set_xlim(self.planning_minx, self.planning_maxx)
71 | self.ax.set_ylim(self.planning_miny, self.planning_maxy)
72 |
73 | plt.pause(self.dt)
74 |
75 | def on_mousepress(self,event):
76 | if not event.dblclick:
77 | if event.button == 1:
78 | self.planning_start = np.array([event.xdata,event.ydata])
79 | if event.button == 3:
80 | self.planning_target = np.array([event.xdata,event.ydata])
81 | if event.button == 2:
82 | self.add_obs(event.xdata,event.ydata)
83 | self.temp_obs = [event.xdata,event.ydata]
84 | def on_mousemove(self,event):
85 | if hasattr(event,"button") and event.button == 2:
86 | dx = event.xdata-self.temp_obs[0]
87 | dy = event.ydata-self.temp_obs[1]
88 | if np.hypot(dx,dy) > self.planning_obs_radius*0.8:
89 | self.temp_obs = [event.xdata,event.ydata]
90 | self.add_obs(*self.temp_obs)
91 | def on_press(self,event):
92 | if(event.key == 'escape'):
93 | self.set_exit()
94 | if(event.key == ' '):
95 | print("---------------------------------\ndo planning...")
96 | print("obstacles : ",self.planning_obs)
97 | print("plan start : ",self.planning_start)
98 | print("plan target : ",self.planning_target)
99 | if self.planning_target is not None and self.planner is not None:
100 | ##### TODO
101 | # px,py = planner.planning(self.planning_obs[:,0],self.planning_obs[:,1], self.planning_start[0],self.planning_start[1],self.planning_target[0],self.planning_target[1],self.planning_minx,self.planning_miny,self.planning_maxx,self.planning_maxy)
102 | px,py = planner.planning(self.planning_obs[:,0],self.planning_obs[:,1], 1.5, self.planning_start[0],self.planning_start[1],self.planning_target[0],self.planning_target[1],self.planning_minx,self.planning_miny,self.planning_maxx,self.planning_maxy)
103 |
104 | self.planning_path = np.vstack([px,py]).T
105 | print("plan path : ",self.planning_path)
106 | else:
107 | print("planner or target is None,please check again.")
108 |
109 | def set_exit(self):
110 | self.NEED_EXIT = True
111 |
112 | if __name__ == "__main__":
113 | planner = None
114 | # planner = AStarPlanner(0.1, 1.5)
115 | planner = AStarPlanner(0.05)
116 |
117 | # planner = RRTPlanner(0.2,1.5)
118 | pg = Playground(planner)
119 | pg.run()
--------------------------------------------------------------------------------