55import tf2_ros
66import tf2_geometry_msgs
77import threading
8- import numpy as np
98
109from geometry_msgs .msg import TwistStamped
11- from geometry_msgs .msg import Point
1210from geometry_msgs .msg import PointStamped
13- from geometry_msgs .msg import Vector3Stamped
14- from geometry_msgs .msg import Vector3
11+ from iarc7_msgs .msg import MotionPointStamped , MotionPointStampedArray
1512
1613from task_utilities .acceleration_limiter import AccelerationLimiter
1714
2522 NopCommand )
2623
2724class BlockRoombaTaskState (object ):
28- init = 0
29- waiting = 1
30- descent = 2
25+ INIT = 0
26+ WAITING = 1
27+ PLANNING = 2
28+ DESCENDING = 3
29+ LANDED = 4
3130
3231class BlockRoombaTask (AbstractTask ):
33-
3432 def __init__ (self , task_request ):
3533 super (BlockRoombaTask , self ).__init__ ()
3634
@@ -39,67 +37,66 @@ def __init__(self, task_request):
3937 if self ._roomba_id == '' :
4038 raise ValueError ('An invalid roomba id was provided to BlockRoombaTask' )
4139
40+ self ._distance_to_roomba = None
4241 self ._roomba_odometry = None
4342 self ._roomba_point = None
4443 self ._limiter = AccelerationLimiter ()
4544
4645 self ._canceled = False
47- self ._last_update_time = None
4846 self ._current_velocity = None
4947 self ._transition = None
5048
49+ self ._target = (0 ,0 )
50+
5151 self ._lock = threading .RLock ()
5252
5353 try :
5454 self ._TRANSFORM_TIMEOUT = rospy .get_param ('~transform_timeout' )
55- self ._MIN_MANEUVER_HEIGHT = rospy .get_param ('~min_maneuver_height' )
5655 self ._MAX_TRANSLATION_SPEED = rospy .get_param ('~max_translation_speed' )
5756 self ._MAX_START_TASK_DIST = rospy .get_param ('~block_roomba_max_start_dist' )
5857 self ._MAX_Z_VELOCITY = rospy .get_param ('~max_z_velocity' )
5958 self ._K_X = rospy .get_param ('~k_term_tracking_x' )
6059 self ._K_Y = rospy .get_param ('~k_term_tracking_y' )
61- self ._descent_velocity = rospy .get_param ('~block_descent_velocity' )
60+ self ._DESCENT_VELOCITY = rospy .get_param ('~block_descent_velocity' )
61+
6262 _roomba_diameter = rospy .get_param ('~roomba_diameter' )
63- _drone_width = rospy .get_param ('~drone_landing_gear_width' )
63+ _drone_width = rospy .get_param ('~drone_landing_gear_width' )
6464 except KeyError as e :
6565 rospy .logerr ('Could not lookup a parameter for block roomba task' )
6666 raise
67- self ._overshoot = (_roomba_diameter + _drone_width )/ 2
68- self ._state = BlockRoombaTaskState .init
67+
68+ # the roomba diameter/2 (radius) is acting as a buffer
69+ self ._overshoot = _roomba_diameter + _drone_width / 2
70+ self ._state = BlockRoombaTaskState .INIT
6971
7072 def get_desired_command (self ):
7173 with self ._lock :
7274 if self ._canceled :
7375 return (TaskCanceled (),)
7476
75- if ( self ._state == BlockRoombaTaskState .init ) :
77+ if self ._state == BlockRoombaTaskState .INIT :
7678 if (not self .topic_buffer .has_roomba_message ()
7779 or not self .topic_buffer .has_odometry_message ()
7880 or not self .topic_buffer .has_landing_message ()):
79- self ._state = BlockRoombaTaskState .waiting
81+ self ._state = BlockRoombaTaskState .WAITING
8082 else :
81- self ._state = BlockRoombaTaskState .descent
83+ self ._state = BlockRoombaTaskState .PLANNING
8284
83- if ( self ._state == BlockRoombaTaskState .waiting ) :
85+ if self ._state == BlockRoombaTaskState .WAITING :
8486 if (not self .topic_buffer .has_roomba_message ()
8587 or not self .topic_buffer .has_odometry_message ()
8688 or not self .topic_buffer .has_landing_message ()):
8789 return (TaskRunning (), NopCommand ())
8890 else :
89- self ._state = BlockRoombaTaskState .descent
91+ self ._state = BlockRoombaTaskState .PLANNING
9092
91- if ( self ._state == BlockRoombaTaskState .descent ) :
93+ if self ._state == BlockRoombaTaskState .PLANNING :
9294 try :
9395 roomba_transform = self .topic_buffer .get_tf_buffer ().lookup_transform (
9496 'level_quad' ,
9597 self ._roomba_id ,
9698 rospy .Time (0 ),
9799 rospy .Duration (self ._TRANSFORM_TIMEOUT ))
98- drone_transform = self .topic_buffer .get_tf_buffer ().lookup_transform (
99- 'level_quad' ,
100- 'map' ,
101- rospy .Time (0 ),
102- rospy .Duration (self ._TRANSFORM_TIMEOUT ))
103100 except (tf2_ros .LookupException ,
104101 tf2_ros .ConnectivityException ,
105102 tf2_ros .ExtrapolationException ) as ex :
@@ -126,33 +123,40 @@ def get_desired_command(self):
126123 roomba_y_velocity = self ._roomba_odometry .twist .twist .linear .y
127124 roomba_velocity = math .sqrt (roomba_x_velocity ** 2 + roomba_y_velocity ** 2 )
128125
129- roomba_vector = Vector3Stamped ()
126+ drone_height = self .topic_buffer .get_odometry_message ().pose .pose .position .z
127+ time_to_descend = drone_height / self ._DESCENT_VELOCITY
128+
129+ roomba_vector_x = roomba_x_velocity / roomba_velocity
130+ roomba_vector_y = roomba_y_velocity / roomba_velocity
130131
131- roomba_vector .vector .x = roomba_x_velocity / roomba_velocity
132- roomba_vector .vector .y = roomba_y_velocity / roomba_velocity
133- roomba_vector .vector .z = 0.0
132+ goal_x = (self ._roomba_point .point .x + self ._overshoot * roomba_vector_x )/ time_to_descend
133+ goal_y = (self ._roomba_point .point .y + self ._overshoot * roomba_vector_y )/ time_to_descend
134134
135- # p-controller
136- x_vel_target = ((self ._roomba_point .point .x + self ._overshoot * roomba_vector .vector .x )
137- * self ._K_X + roomba_x_velocity )
138- y_vel_target = ((self ._roomba_point .point .y + self ._overshoot * roomba_vector .vector .y )
139- * self ._K_Y + roomba_y_velocity )
140-
141- z_vel_target = self ._descent_velocity
135+ # we need a better way to plan
136+ self ._target = (goal_x , goal_y )
142137
143- #caps velocity
138+ self ._state = BlockRoombaTaskState .DESCENDING
139+
140+ if self ._state == BlockRoombaTaskState .DESCENDING :
141+
142+ x_vel_target = self ._target [0 ]
143+ y_vel_target = self ._target [1 ]
144+
145+ z_vel_target = self ._DESCENT_VELOCITY
146+
147+ # cap velocity
144148 vel_target = math .sqrt (x_vel_target ** 2 + y_vel_target ** 2 )
145149
146150 if vel_target > self ._MAX_TRANSLATION_SPEED :
147151 x_vel_target = x_vel_target * (self ._MAX_TRANSLATION_SPEED / vel_target )
148152 y_vel_target = y_vel_target * (self ._MAX_TRANSLATION_SPEED / vel_target )
149-
153+
150154 if (abs (z_vel_target ) > self ._MAX_Z_VELOCITY ):
151155 z_vel_target = z_vel_target / abs (z_vel_target ) * self ._MAX_Z_VELOCITY
152156 rospy .logwarn ("Max Z velocity reached in block roomba" )
153157
154158 desired_vel = [x_vel_target , y_vel_target , z_vel_target ]
155-
159+
156160 odometry = self .topic_buffer .get_odometry_message ()
157161 drone_vel_x = odometry .twist .twist .linear .x
158162 drone_vel_y = odometry .twist .twist .linear .y
@@ -171,7 +175,7 @@ def get_desired_command(self):
171175 velocity .twist .linear .z = desired_vel [2 ]
172176
173177 self ._current_velocity = desired_vel
174-
178+
175179 return (TaskRunning (), VelocityCommand (velocity ))
176180
177181 return (TaskAborted (msg = 'Illegal state reached in Block Roomba Task' ),)
@@ -183,14 +187,14 @@ def _check_max_roomba_range(self):
183187 for odometry in self .topic_buffer .get_roomba_message ().data :
184188 if odometry .child_frame_id == self ._roomba_id :
185189 self ._roomba_odometry = odometry
186- self ._roomba_found = True
187- _distance_to_roomba = math .sqrt (self ._roomba_point .point .x ** 2 +
190+ self ._roomba_found = True
191+ self . _distance_to_roomba = math .sqrt (self ._roomba_point .point .x ** 2 +
188192 self ._roomba_point .point .y ** 2 )
189- return (_distance_to_roomba <= (self ._MAX_START_TASK_DIST + self ._overshoot ))
193+ return (self . _distance_to_roomba <= (self ._MAX_START_TASK_DIST + self ._overshoot ))
190194 return False
191195
192196 def cancel (self ):
193- rospy .loginfo ('HitRoomba Task canceled' )
197+ rospy .loginfo ('BlockRoombaTask canceled' )
194198 self ._canceled = True
195199 return True
196200
0 commit comments