Skip to content

Commit 04144aa

Browse files
committed
Implement LocalPlanExecutor
1 parent 33fdbea commit 04144aa

File tree

15 files changed

+662
-74
lines changed

15 files changed

+662
-74
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ openrr-nav = "0.1"
1414

1515
anyhow = "1"
1616
arci = "0.1"
17+
arci-urdf-viz = "0.1"
1718
bevy = "0.11"
1819
bevy_egui = "0.21"
1920
image = "0.24"
@@ -28,6 +29,7 @@ tonic-build = "0.10"
2829
serde = { version = "1.0", features = ["derive"] }
2930
serde_yaml = "0.9"
3031
clap = { version = "4.4", features = ["derive", "env"] }
32+
yaml-rust = "0.4"
3133

3234
[patch.crates-io]
3335
grid_map = { path = "grid_map" }

openrr-nav-viewer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ clap.workspace = true
2424

2525
[dev-dependencies]
2626
anyhow.workspace = true
27+
arci-urdf-viz.workspace = true
2728
rand.workspace = true
2829
rrt.workspace = true
2930

openrr-nav-viewer/examples/controller.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,14 @@ async fn controller(
7979
add_target_position_to_path(result, &Pose::new(Vector2::new(goal[0], goal[1]), goal[2]));
8080
api.set_global_path(pb::RobotPath::from(robot_path_from_vec_vec(result.clone())))
8181
.await?;
82-
let path_grid = result
83-
.iter()
84-
.map(|p| map.to_grid(p[0], p[1]).unwrap())
85-
.collect::<Vec<_>>();
8682

8783
for p in &result {
8884
map.set_value(&map.to_grid(p[0], p[1]).unwrap(), 0).unwrap();
8985
}
9086

91-
let path_distance_map = path_distance_map(&map, &path_grid).unwrap();
87+
let path_distance_map = path_distance_map(&map, &result).unwrap();
9288

93-
let goal_grid = map.to_grid(goal[0], goal[1]).unwrap();
94-
let goal_distance_map = goal_distance_map(&map, &goal_grid).unwrap();
89+
let goal_distance_map = goal_distance_map(&map, &goal).unwrap();
9590

9691
let obstacle_distance_map = obstacle_distance_map(&map).unwrap();
9792

@@ -147,10 +142,9 @@ async fn controller(
147142
for i in 0..300 {
148143
// let dynamic_map = new_dynamic_sample_map(i);
149144
let dynamic_map = new_sample_map();
150-
let path_distance_map = openrr_nav::path_distance_map(&dynamic_map, &path_grid).unwrap();
145+
let path_distance_map = openrr_nav::path_distance_map(&dynamic_map, &result).unwrap();
151146

152-
let goal_grid = map.to_grid(goal[0], goal[1]).unwrap();
153-
let goal_distance_map = openrr_nav::goal_distance_map(&dynamic_map, &goal_grid).unwrap();
147+
let goal_distance_map = openrr_nav::goal_distance_map(&dynamic_map, &goal).unwrap();
154148

155149
let obstacle_distance_map = openrr_nav::obstacle_distance_map(&dynamic_map).unwrap();
156150

openrr-nav-viewer/examples/dwa_gui.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,14 @@ fn main() {
8282
let mut locked_robot_path = cloned_nav.robot_path.lock().unwrap();
8383
locked_robot_path.set_global_path(robot_path_from_vec_vec(result.clone()));
8484
}
85-
let path_grid = result
86-
.iter()
87-
.map(|p| map.to_grid(p[0], p[1]).unwrap())
88-
.collect::<Vec<_>>();
8985

9086
for p in &result {
9187
map.set_value(&map.to_grid(p[0], p[1]).unwrap(), 0).unwrap();
9288
}
9389

94-
let path_distance_map = path_distance_map(&map, &path_grid).unwrap();
90+
let path_distance_map = path_distance_map(&map, &result).unwrap();
9591

96-
let goal_grid = map.to_grid(goal[0], goal[1]).unwrap();
97-
let goal_distance_map = goal_distance_map(&map, &goal_grid).unwrap();
92+
let goal_distance_map = goal_distance_map(&map, &goal).unwrap();
9893

9994
let obstacle_distance_map = obstacle_distance_map(&map).unwrap();
10095

@@ -129,12 +124,9 @@ fn main() {
129124
for i in 0..300 {
130125
// let dynamic_map = new_dynamic_sample_map(i);
131126
let dynamic_map = new_sample_map();
132-
let path_distance_map =
133-
openrr_nav::path_distance_map(&dynamic_map, &path_grid).unwrap();
127+
let path_distance_map = openrr_nav::path_distance_map(&dynamic_map, &result).unwrap();
134128

135-
let goal_grid = map.to_grid(goal[0], goal[1]).unwrap();
136-
let goal_distance_map =
137-
openrr_nav::goal_distance_map(&dynamic_map, &goal_grid).unwrap();
129+
let goal_distance_map = openrr_nav::goal_distance_map(&dynamic_map, &goal).unwrap();
138130

139131
let obstacle_distance_map = openrr_nav::obstacle_distance_map(&dynamic_map).unwrap();
140132

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
use arci::{nalgebra as na, Localization};
2+
use arci_urdf_viz::UrdfVizWebClient;
3+
use grid_map::*;
4+
use openrr_nav::*;
5+
use openrr_nav_viewer::{BevyAppNav, NavigationViz};
6+
use std::sync::{Arc, Mutex};
7+
8+
fn new_sample_map() -> GridMap<u8> {
9+
let mut map = grid_map::GridMap::<u8>::new(
10+
Position::new(-1.05, -1.05),
11+
Position::new(10.05, 10.05),
12+
0.1,
13+
);
14+
15+
for i in 0..40 {
16+
for j in 0..20 {
17+
map.set_obstacle(&Grid {
18+
x: 40 + i,
19+
y: 30 + j,
20+
});
21+
}
22+
}
23+
for i in 0..20 {
24+
for j in 0..30 {
25+
map.set_obstacle(&Grid {
26+
x: 60 + i,
27+
y: 65 + j,
28+
});
29+
}
30+
}
31+
32+
map
33+
}
34+
35+
fn robot_path_from_vec_vec(path: Vec<Vec<f64>>) -> RobotPath {
36+
let mut robot_path_inner = vec![];
37+
for p in path {
38+
let pose = na::Isometry2::new(na::Vector2::new(p[0], p[1]), 0.);
39+
40+
robot_path_inner.push(pose);
41+
}
42+
RobotPath(robot_path_inner)
43+
}
44+
45+
fn main() {
46+
let client = UrdfVizWebClient::default();
47+
client.run_send_velocity_thread();
48+
49+
let nav = NavigationViz::default();
50+
51+
let start = client.current_pose("").unwrap();
52+
let start = [
53+
start.translation.x,
54+
start.translation.y,
55+
start.rotation.angle(),
56+
];
57+
let goal = [9.0, 8.0, std::f64::consts::FRAC_PI_3];
58+
{
59+
let mut locked_start = nav.start_position.lock().unwrap();
60+
*locked_start = Pose::new(Vector2::new(start[0], start[1]), start[2]);
61+
let mut locked_goal = nav.goal_position.lock().unwrap();
62+
*locked_goal = Pose::new(Vector2::new(goal[0], goal[1]), goal[2]);
63+
}
64+
65+
let cloned_nav = nav.clone();
66+
67+
let planner = DwaPlanner::new_from_config(format!(
68+
"{}/../openrr-nav/config/dwa_parameter_config.yaml",
69+
env!("CARGO_MANIFEST_DIR")
70+
))
71+
.unwrap();
72+
73+
{
74+
let mut locked_planner = cloned_nav.planner.lock().unwrap();
75+
*locked_planner = planner.clone();
76+
}
77+
78+
let mut local_plan_executor = LocalPlanExecutor::new(
79+
Arc::new(Mutex::new(client.clone())),
80+
Arc::new(Mutex::new(client.clone())),
81+
"".to_owned(),
82+
planner,
83+
0.1,
84+
);
85+
86+
std::thread::spawn(move || loop {
87+
if cloned_nav.is_run.lock().unwrap().clone() {
88+
let mut map = new_sample_map();
89+
let start;
90+
let goal;
91+
{
92+
let current_pose = client.current_pose("").unwrap();
93+
let mut locked_start = cloned_nav.start_position.lock().unwrap();
94+
*locked_start = current_pose;
95+
start = [
96+
current_pose.translation.x,
97+
current_pose.translation.y,
98+
current_pose.rotation.angle(),
99+
];
100+
101+
let locked_goal = cloned_nav.goal_position.lock().unwrap();
102+
goal = [
103+
locked_goal.translation.x,
104+
locked_goal.translation.y,
105+
locked_goal.rotation.angle(),
106+
];
107+
}
108+
109+
let mut global_plan = GlobalPlan::new(map.clone(), start, goal);
110+
111+
let result = global_plan.global_plan();
112+
{
113+
let mut locked_robot_path = cloned_nav.robot_path.lock().unwrap();
114+
locked_robot_path.set_global_path(robot_path_from_vec_vec(result.clone()));
115+
}
116+
117+
let mut cost_maps = CostMaps::new(&map, &result, &start, &goal);
118+
let mut angle_table = AngleTable::new(start[2], goal[2]);
119+
120+
for p in result.iter() {
121+
map.set_value(&map.to_grid(p[0], p[1]).unwrap(), 0).unwrap();
122+
}
123+
124+
local_plan_executor.set_cost_maps(cost_maps.layered_grid_map());
125+
{
126+
let mut locked_layered_grid_map = cloned_nav.layered_grid_map.lock().unwrap();
127+
*locked_layered_grid_map = cost_maps.layered_grid_map();
128+
}
129+
130+
local_plan_executor.set_angle_table(angle_table.angle_table());
131+
{
132+
let mut locked_angle_table = cloned_nav.angle_table.lock().unwrap();
133+
*locked_angle_table = angle_table.angle_table();
134+
}
135+
136+
let mut current_pose;
137+
let goal_pose = Pose::new(Vector2::new(goal[0], goal[1]), goal[2]);
138+
139+
const STEP: usize = 2000;
140+
for i in 0..STEP {
141+
current_pose = local_plan_executor.current_pose().unwrap();
142+
143+
cost_maps.update(
144+
&None,
145+
&result,
146+
&[current_pose.translation.x, current_pose.translation.y],
147+
&[],
148+
);
149+
150+
angle_table.update(Some(current_pose), &result);
151+
152+
local_plan_executor.set_cost_maps(cost_maps.layered_grid_map());
153+
{
154+
let mut locked_layered_grid_map = cloned_nav.layered_grid_map.lock().unwrap();
155+
*locked_layered_grid_map = cost_maps.layered_grid_map();
156+
}
157+
158+
local_plan_executor.set_angle_table(angle_table.angle_table());
159+
{
160+
let mut locked_angle_table = cloned_nav.angle_table.lock().unwrap();
161+
*locked_angle_table = angle_table.angle_table();
162+
}
163+
164+
local_plan_executor.exec_once().unwrap();
165+
166+
{
167+
let mut locked_robot_pose = cloned_nav.robot_pose.lock().unwrap();
168+
*locked_robot_pose = current_pose;
169+
}
170+
171+
println!(
172+
"[ {:4} / {} ] X: {:.3}, Y: {:.3}, THETA: {:.3}",
173+
i + 1,
174+
STEP,
175+
current_pose.translation.x,
176+
current_pose.translation.y,
177+
current_pose.rotation.angle()
178+
);
179+
std::thread::sleep(std::time::Duration::from_millis(5));
180+
181+
const GOAL_THRESHOLD_DISTANCE: f64 = 0.1;
182+
const GOAL_THRESHOLD_ANGLE_DIFFERENCE: f64 = 0.4;
183+
if (goal_pose.translation.vector - current_pose.translation.vector).norm()
184+
< GOAL_THRESHOLD_DISTANCE
185+
&& (goal_pose.rotation.angle() - current_pose.rotation.angle()).abs()
186+
< GOAL_THRESHOLD_ANGLE_DIFFERENCE
187+
{
188+
println!("GOAL! count = {i}");
189+
break;
190+
}
191+
}
192+
local_plan_executor.stop().unwrap();
193+
{
194+
let mut is_run = cloned_nav.is_run.lock().unwrap();
195+
*is_run = false;
196+
}
197+
}
198+
});
199+
200+
let bevy_cloned_nav = nav.clone();
201+
let mut app = BevyAppNav::new();
202+
app.setup(bevy_cloned_nav);
203+
app.run();
204+
}

openrr-nav-viewer/src/nav_viz.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66
sync::{Arc, Mutex},
77
};
88

9-
#[derive(Debug, Clone, Resource)]
9+
#[derive(Debug, Clone, Resource, Default)]
1010
pub struct NavigationViz {
1111
pub layered_grid_map: Arc<Mutex<LayeredGridMap<u8>>>,
1212
pub angle_table: Arc<Mutex<HashMap<String, f64>>>,

openrr-nav/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ repository.workspace = true
1010
[dependencies]
1111
arci.workspace = true
1212
grid_map.workspace = true
13+
rand.workspace = true
14+
rrt.workspace = true
1315
thiserror.workspace = true
1416
serde.workspace = true
1517
serde_yaml.workspace = true
18+
yaml-rust.workspace = true
1619

1720
[dev-dependencies]
1821
bevy.workspace = true
19-
rand.workspace = true
20-
rrt.workspace = true
2122

2223
[lints]
2324
workspace = true

openrr-nav/examples/dwa.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,14 @@ fn main() {
4141
)
4242
.unwrap();
4343

44-
let path_grid = result
45-
.iter()
46-
.map(|p| map.to_grid(p[0], p[1]).unwrap())
47-
.collect::<Vec<_>>();
48-
49-
for p in result {
44+
for p in result.iter() {
5045
map.set_value(&map.to_grid(p[0], p[1]).unwrap(), 0).unwrap();
5146
}
5247
show_ascii_map(&map, 1.0);
53-
let path_distance_map = path_distance_map(&map, &path_grid).unwrap();
48+
let path_distance_map = path_distance_map(&map, &result).unwrap();
5449
show_ascii_map(&path_distance_map, 1.0);
5550
println!("=======================");
56-
let goal_grid = map.to_grid(goal[0], goal[1]).unwrap();
57-
let goal_distance_map = goal_distance_map(&map, &goal_grid).unwrap();
51+
let goal_distance_map = goal_distance_map(&map, &goal).unwrap();
5852
show_ascii_map(&goal_distance_map, 0.1);
5953
println!("=======================");
6054
let obstacle_distance_map = obstacle_distance_map(&map).unwrap();

openrr-nav/src/angle_table.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use std::collections::HashMap;
2+
3+
use crate::{utils::nearest_path_point, Pose};
4+
5+
const ROTATION_COST_NAME: &str = "rotation";
6+
const PATH_DIRECTION_COST_NAME: &str = "path_direction";
7+
const GOAL_DIRECTION_COST_NAME: &str = "goal_direction";
8+
9+
#[derive(Debug)]
10+
pub struct AngleTable(HashMap<String, f64>);
11+
12+
impl AngleTable {
13+
pub fn new(start: f64, goal: f64) -> Self {
14+
let mut angles = HashMap::new();
15+
16+
angles.insert(ROTATION_COST_NAME.to_owned(), start);
17+
angles.insert(PATH_DIRECTION_COST_NAME.to_owned(), start);
18+
angles.insert(GOAL_DIRECTION_COST_NAME.to_owned(), goal);
19+
20+
Self(angles)
21+
}
22+
23+
pub fn update(&mut self, current_pose: Option<Pose>, path: &[Vec<f64>]) {
24+
if let Some(pose) = current_pose {
25+
self.0
26+
.insert(ROTATION_COST_NAME.to_owned(), pose.rotation.angle());
27+
28+
if !path.is_empty() {
29+
let nearest_path_point =
30+
nearest_path_point(path, [pose.translation.x, pose.translation.y]);
31+
if let Some(p) = nearest_path_point {
32+
self.0.insert(PATH_DIRECTION_COST_NAME.to_owned(), p.1[2]);
33+
}
34+
}
35+
}
36+
}
37+
38+
pub fn angle_table(&self) -> HashMap<String, f64> {
39+
self.0.clone()
40+
}
41+
}

0 commit comments

Comments
 (0)