Skip to content

Commit 7cbd2a2

Browse files
committed
osgar.explore: add debug_callback to follow_wall_angle
1 parent a601b3a commit 7cbd2a2

3 files changed

Lines changed: 93 additions & 5 deletions

File tree

osgar/explore.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def tangent_circle(dist, radius):
3535
return math.radians(100)
3636

3737

38-
def follow_wall_angle(laser_data, radius, right_wall=False):
38+
def follow_wall_angle(laser_data, radius, right_wall=False, max_obstacle_distance=4.0, debug_callback=None):
3939
"""
4040
Find the angle to the closest point in laser scan (either on the left or right side).
4141
Then calculate an angle to a free space as tangent to circle of given radius.
@@ -47,7 +47,7 @@ def follow_wall_angle(laser_data, radius, right_wall=False):
4747
mask = (data <= 300) # ignore internal reflections
4848
data[mask] = 20000
4949

50-
mask = (data >= 4000) # ignore obstacles beyond 4m
50+
mask = (data >= max_obstacle_distance * 1000) # ignore obstacles beyond 4m
5151
data[mask] = 20000
5252

5353
# To make the code simpler, let's pretend we follow the right wall and flip
@@ -107,12 +107,22 @@ def follow_wall_angle(laser_data, radius, right_wall=False):
107107
else:
108108
tangent_angle = tangent_circle(last_wall_distance, radius)
109109

110-
111110
laser_angle = math.radians(-135 + last_wall_idx * deg_resolution)
112111
total_angle = laser_angle + tangent_angle
113112
if not right_wall:
114113
total_angle = -total_angle
115114

115+
if debug_callback is not None:
116+
117+
def deg(index):
118+
ret = -135 + index * deg_resolution
119+
return ret if right_wall else -ret
120+
121+
def rad(index):
122+
return math.radians(deg(index))
123+
124+
debug_callback(laser_data, max_obstacle_distance, rad(wall_start_idx), rad(last_wall_idx), total_angle)
125+
116126
return total_angle
117127

118128

osgar/lib/drawscan.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import cv2
2+
import numpy as np
3+
import math
4+
import osgar.explore
5+
6+
NO_MEASUREMENT = 0
7+
MAX_OBSTACLE_DISTANCE = 20
8+
9+
10+
def draw_scan(scan, max_obstacle_distance=None, scan_left=135, scan_right=-135):
11+
if max_obstacle_distance is None:
12+
max_obstacle_distance = MAX_OBSTACLE_DISTANCE
13+
n = len(scan)
14+
scan = np.asarray(scan) / 1000
15+
16+
angles = np.linspace(math.radians(scan_right), math.radians(scan_left), n).reshape((1, -1))
17+
angles_cos = np.cos(angles)
18+
angles_sin = np.sin(angles)
19+
is_valid = scan != NO_MEASUREMENT
20+
valid_scan = scan[is_valid]
21+
is_valid = is_valid.reshape((1, -1))
22+
acoss = angles_cos[is_valid]
23+
asins = angles_sin[is_valid]
24+
x = acoss * valid_scan
25+
y = asins * valid_scan
26+
far_map = valid_scan > max_obstacle_distance
27+
28+
height_px = 768
29+
width_px = 1024
30+
img = np.zeros((height_px, width_px, 3), dtype=np.uint8)
31+
32+
scale = 50
33+
for ix, iy, is_far in zip(x, y, far_map):
34+
point = (width_px//2 - int(iy*scale), height_px//2 - int(ix*scale))
35+
color = (0, 255, 0) if not is_far else (120, 120, 120)
36+
cv2.circle(img, point, radius=3, color=color, thickness=-1)
37+
38+
point = (width_px//2, height_px//2)
39+
point2 = (width_px//2, height_px//2-20)
40+
cv2.drawMarker(img, point, color=(0, 0, 255), markerType=cv2.MARKER_DIAMOND, thickness=3, markerSize=10)
41+
cv2.line(img, point, point2, thickness=3, color=(0, 0, 255))
42+
return img

subt/main.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class SubTChallenge:
146146
def __init__(self, config, bus):
147147
self.bus = bus
148148
bus.register("desired_speed", "pose2d", "artf_xyz", "pose3d", "stdout", "request_origin")
149+
self.verbose = False
149150
self.start_pose = None
150151
self.traveled_dist = 0.0
151152
self.time = None
@@ -257,7 +258,11 @@ def go_safely(self, desired_direction):
257258
safety, safe_direction = 1.0, desired_direction
258259
else:
259260
safety, safe_direction = self.local_planner.recommend(desired_direction)
260-
#print(self.time,"safety:%f desired:%f safe_direction:%f"%(safety, desired_direction, safe_direction))
261+
if self.verbose:
262+
heading = math.degrees(quaternion.heading(self.orientation))
263+
desired_deg = math.degrees(desired_direction)
264+
safe_deg = math.degrees(safe_direction)
265+
print(self.time, self.sim_time_sec, f"safety:{safety:.2f} desired:{desired_deg:.2f}° safe_direction: {safe_deg:.2f}°")
261266
#desired_angular_speed = 1.2 * safe_direction
262267
desired_angular_speed = 0.9 * safe_direction
263268
size = len(self.scan)
@@ -326,7 +331,8 @@ def follow_wall(self, radius, right_wall=False, timeout=timedelta(hours=3), dist
326331
if self.use_center:
327332
desired_direction = 0
328333
else:
329-
desired_direction = follow_wall_angle(self.scan, radius=radius, right_wall=right_wall)
334+
debug_callback = debug_follow_wall if self.verbose else None
335+
desired_direction = follow_wall_angle(self.scan, radius=radius, right_wall=right_wall, debug_callback=debug_callback)
330336
self.go_safely(desired_direction)
331337
if dist_limit is not None:
332338
if dist_limit < abs(self.traveled_dist - start_dist): # robot can return backward -> abs()
@@ -1006,6 +1012,36 @@ def join(self, timeout=None):
10061012
self.thread.join(timeout)
10071013

10081014

1015+
def debug_follow_wall(laser_data, max_obstacle_distance_m, start_rad, last_rad, total_rad):
1016+
from osgar.lib.drawscan import draw_scan
1017+
import cv2
1018+
1019+
img = draw_scan(laser_data, max_obstacle_distance=max_obstacle_distance_m)
1020+
width_px, height_px = img.shape[1], img.shape[0]
1021+
scale = 300
1022+
dest_x = math.cos(start_rad)
1023+
dest_y = math.sin(start_rad)
1024+
point = (width_px//2 - int(dest_y*scale), height_px//2 - int(dest_x*scale))
1025+
cv2.line(img, (width_px//2, height_px//2), point, color=(255,255,255))
1026+
1027+
dest_x = math.cos(last_rad)
1028+
dest_y = math.sin(last_rad)
1029+
point = (width_px//2 - int(dest_y*scale), height_px//2 - int(dest_x*scale))
1030+
cv2.line(img, (width_px//2, height_px//2), point, color=(120,255,255))
1031+
1032+
dest_x = math.cos(total_rad)
1033+
dest_y = math.sin(total_rad)
1034+
point = (width_px//2 - int(dest_y*scale), height_px//2 - int(dest_x*scale))
1035+
cv2.line(img, (width_px//2, height_px//2), point, color=(120,120,255))
1036+
1037+
point = (width_px//2, height_px//4)
1038+
cv2.line(img, (width_px//2, height_px//2), point, color=(120,120,120))
1039+
1040+
#print(f"start {math.degrees(start_rad):.2f}°", f"last wall {math.degrees(last_rad):.2f}°" , f"desired {math.degrees(total_rad):.2f}°")
1041+
cv2.imshow("follow_wall_angle", img)
1042+
cv2.waitKey()
1043+
1044+
10091045
def main():
10101046
import argparse
10111047
from osgar.lib.config import config_load

0 commit comments

Comments
 (0)