4 from std_msgs.msg
import ColorRGBA
5 from sensor_msgs.msg
import LaserScan
6 from drive_msgs.msg
import drive_param
8 from rviz_geometry
import show_circle_in_rviz, show_line_in_rviz
10 from circle
import Circle, Point
16 from dynamic_reconfigure.server
import Server
17 from wallfollowing2.cfg
import wallfollowing2Config
19 TOPIC_DRIVE_PARAMETERS =
"/input/drive_param/autonomous" 20 TOPIC_LASER_SCAN =
"/scan" 27 self.
names = default_values.keys()
28 for name
in self.
names:
29 setattr(self, name, default_values[name])
32 return '\n'.join(name +
": " + str(getattr(self, name))
33 for name
in self.
names)
55 return self.
p * error + self.
i * self.
integral + self.
d * derivative
58 def map(in_lower, in_upper, out_lower, out_upper, value):
59 result = out_lower + (out_upper - out_lower) * \
60 (value - in_lower) / (in_upper - in_lower)
61 return min(out_upper, max(out_lower, result))
65 message = drive_param()
67 message.velocity = velocity
68 drive_parameters_publisher.publish(message)
72 ranges = np.array(laser_scan.ranges)
79 laser_range = laser_scan.angle_max - laser_scan.angle_min
80 usable_range = math.radians(parameters.usable_laser_range)
81 if usable_range < laser_range:
82 skip_left = int((-laser_scan.angle_min - usable_range / 2) / laser_range * ranges.shape[0])
83 skip_right = int((laser_scan.angle_max - usable_range / 2) / laser_range * ranges.shape[0])
84 angles = angles[skip_left:-1 - skip_right]
85 ranges = ranges[skip_left:-1 - skip_right]
87 inf_mask = np.isinf(ranges)
89 ranges = ranges[~inf_mask]
90 angles = angles[~inf_mask]
92 points = np.zeros((ranges.shape[0], 2))
93 points[:, 0] = -np.sin(angles) * ranges
94 points[:, 1] = np.cos(angles) * ranges
100 margin = int(points.shape[0] * margin_relative)
102 relative = points[margin + 1:-margin, :] - points[margin:-margin - 1, :]
103 distances = np.linalg.norm(relative, axis=1)
105 return margin + np.argmax(distances) + 1
111 prediction_distance = parameters.corner_cutting + \
112 parameters.straight_smoothing * last_speed
114 predicted_car_position =
Point(0, prediction_distance)
115 left_point = left_circle.get_closest_point(predicted_car_position)
116 right_point = right_circle.get_closest_point(predicted_car_position)
118 target_position =
Point(
119 (left_point.x + right_point.x) / 2,
120 (left_point.y + right_point.y) / 2)
121 error = (target_position.x - predicted_car_position.x) / \
123 if math.isnan(error)
or math.isinf(error):
126 steering_angle = pid.update_and_get_correction(
129 radius = min(left_circle.radius, right_circle.radius)
130 speed_limit_radius =
map(parameters.radius_lower, parameters.radius_upper, 0, 1, radius)
131 speed_limit_error = max(0, 1 + parameters.steering_slow_down_dead_zone - abs(error) * parameters.steering_slow_down)
132 speed_limit_acceleration = last_speed + parameters.max_acceleration * delta_time
133 speed_limit_barrier =
map(parameters.barrier_lower_limit, parameters.barrier_upper_limit, 0, 1, barrier) ** parameters.barrier_exponent
135 relative_speed = min(
138 speed_limit_acceleration,
141 last_speed = relative_speed
142 speed =
map(0, 1, parameters.min_throttle, parameters.max_throttle, relative_speed)
143 steering_angle = steering_angle *
map(parameters.high_speed_steering_limit_dead_zone, 1, 1, parameters.high_speed_steering_limit, relative_speed)
144 drive(steering_angle, speed)
147 color=ColorRGBA(1, 1, 1, 0.3), line_width=0.005)
149 color=ColorRGBA(1, 1, 1, 0.3), line_width=0.005)
151 target_position], color=ColorRGBA(1, 0.4, 0, 1))
154 5, [
Point(-2, barrier),
Point(2, barrier)], color=ColorRGBA(1, 1, 0, 1))
158 if parameters
is None:
163 if points.shape[0] == 0:
164 rospy.logwarn(
"Skipping current laser scan message since it contains no finite values.")
169 right_wall = points[:split:4, :]
170 left_wall = points[split::4, :]
172 left_circle = Circle.fit(left_wall)
173 right_circle = Circle.fit(right_wall)
175 barrier_start = int(points.shape[0] * (0.5 - parameters.barrier_size_realtive))
176 barrier_end = int(points.shape[0] * (0.5 + parameters.barrier_size_realtive))
177 barrier = np.max(points[barrier_start: barrier_end, 1])
179 follow_walls(left_circle, right_circle, barrier, delta_time)
191 scan_time = scan_message.header.stamp.to_sec()
192 if last_scan
is not None and abs(scan_time - last_scan) > 0.0001
and scan_time > last_scan:
193 delta_time = scan_time - last_scan
196 last_scan = scan_time
202 pid.p = parameters.controller_p
203 pid.i = parameters.controller_i
204 pid.d = parameters.controller_d
208 rospy.init_node(
'wallfollowing', anonymous=
True)
212 rospy.Subscriber(TOPIC_LASER_SCAN, LaserScan, laser_callback)
213 drive_parameters_publisher = rospy.Publisher(
214 TOPIC_DRIVE_PARAMETERS, drive_param, queue_size=1)
216 Server(wallfollowing2Config, dynamic_configuration_callback)
218 while not rospy.is_shutdown():
def get_scan_as_cartesian(laser_scan)
def show_line_in_rviz(id, points, color, line_width=0.02)
def dynamic_configuration_callback(config, level)
def handle_scan(laser_scan, delta_time)
def find_left_right_border(points, margin_relative=0.1)
def __init__(self, default_values)
def map(in_lower, in_upper, out_lower, out_upper, value)
def show_circle_in_rviz(circle, wall, id)
def drive(angle, velocity)
def update_and_get_correction(self, error, delta_time)
def laser_callback(scan_message)
def follow_walls(left_circle, right_circle, barrier, delta_time)
def __init__(self, p, i, d, anti_windup=0.2)