def isStateValid(self,state): # Let's pretend that the validity check is computationally relatively # expensive to emphasize the benefit of explicitly generating valid # samples sleep(.001) # Valid states satisfy the following constraints: # inside the current region and the next region if self.Space_Dimension == 3: region_considered = Polygon.Polygon(self.nextAndcurrentRegionPoly) bottom = state.getZ()-self.height/2 # bottom of the robot for i, name in enumerate(self.original_map['polygon']): if self.original_map['isObstacle'][name] is True: if self.original_map['height'][name] >= bottom: region_considered -=self.original_map['polygon'][name] state_polygon = PolyShapes.Circle(self.radius,(state.getX(),state.getY())) current_region = self.proj.rfi.regions[self.current_reg].name next_region = self.proj.rfi.regions[self.next_reg].name if self.currentRegionPoly.covers(state_polygon): height = self.map['height'][current_region] elif self.nextRegionPoly.covers(state_polygon): height = self.map['height'][next_region] else: height = min(self.map['height'][current_region],self.map['height'][next_region]) return region_considered.covers(state_polygon) and (state.getZ()+self.height/2) < height and (state.getZ()-self.height/2) > 0 else: return self.nextAndcurrentRegionPoly.covers(PolyShapes.Circle(self.radius,(state.getX(),state.getY())))
def __init__(self, proj, shared_data, robot_type): """ Bug alogorithm motion planning controller robot_type (int): Which robot is used for execution. pioneer is 1, ODE is 2 (default=1) """ self.velocity_count_thres = 100 self.velocity_count = 0 #operate_system (int): Which operating system is used for execution. Ubuntu and Mac is 1, Windows is 2 if sys.platform in ['win32', 'cygwin']: self.operate_system = 2 else: self.operate_system = 1 # Information about the robot ## 1: Pioneer ; 2: 0DE if robot_type not in [1, 2]: robot_type = 1 self.system = robot_type #settings for Ubuntu or Mac plotting (only when you set operate_system = 1) self.PLOT = False # plot with matplot self.PLOT_M_LINE = False # plot m-line self.PLOT_EXIT = False # plot exit point of a region self.PLOT_OVERLAP = False # plot overlap area with the obstacle #settings for Windows (only when you set operate_system = 2) self.PLOT_WINDOWS = True # Get references to handlers we'll need to communicate with self.drive_handler = proj.h_instance['drive'] self.pose_handler = proj.h_instance['pose'] if self.system == 1: self.robocomm = shared_data['robocomm'] # Get information about regions self.proj = proj self.coordmap_map2lab = proj.coordmap_map2lab self.coordmap_lab2map = proj.coordmap_lab2map self.last_warning = 0 ################################### ########used by Bug algorithm###### ################################### # PARAMETERS #for plotting self.time = time.clock() self.time_thres = 1 # Pioneer related parameters self.PioneerWidthHalf = 0.20 #0.25 # (m) width of Pioneer #0.20 self.PioneerLengthHalf = 0.25 #0.30 (m) lenght of Pioneer #0.25 # Real Robot polygon related parameters self.boxRealVertical = self.PioneerLengthHalf * 2 self.boxRealHorizontal = self.PioneerWidthHalf * 2.5 self.boxRealVertical_shift = self.boxRealVertical / 2 self.boxRealHorizontal_shift = self.boxRealHorizontal / 2 # Pioneer Range related parameters self.range = 2 * self.PioneerLengthHalf + 0.40 # (m) specify the range of the robot (when the normal circle range cannot detect obstacle) #0.85 self.obsRange = self.range * 0.7 # (m) range that says the robot detects obstacles #0.25 self.shift = 0.20 # How far the range is shifted to ensure it is sensing region in front is bigger 0.20 self.boxVertical = self.obsRange * 2 # box cutting from range of Pioneer self.boxHorizontal = self.obsRange * 2 # box cutting from range of Pioneer self.boxVertical_shift = self.boxVertical + self.boxRealVertical / 2 * 1.5 # vertical shifting of box self.boxHorizontal_shift = self.boxHorizontal / 2 # horizontal shifting of the box ## 2: 0DE self.factorODE = 30 # 30 works better than 50 if self.system == 2: self.PioneerWidthHalf = self.PioneerWidthHalf * self.factorODE self.PioneerLengthHalf = self.PioneerLengthHalf * self.factorODE self.range = self.range * self.factorODE self.obsRange = self.obsRange * self.factorODE self.shift = self.shift * self.factorODE self.boxVertical = self.boxVertical * self.factorODE self.boxHorizontal = self.boxHorizontal * self.factorODE self.boxVertical_shift = self.boxVertical_shift * self.factorODE self.boxHorizontal_shift = self.boxHorizontal_shift * self.factorODE self.boxRealVertical = self.boxRealVertical * self.factorODE self.boxRealHorizontal = self.boxRealHorizontal * self.factorODE self.boxRealVertical_shift = self.boxRealVertical_shift * self.factorODE self.boxRealHorizontal_shift = self.boxRealHorizontal_shift * self.factorODE self.map = {} # dictionary for all the regions self.all = Polygon.Polygon() # Polygon with all the regions self.map_work = Polygon.Polygon( ) # Polygon of the current region and next region considered self.ogr = Polygon.Polygon( ) #Polygon built from occupancy grid data points self.previous_current_reg = None # previous current region self.currentRegionPoly = None # current region's polygon self.nextRegionPoly = None # next region's polygon self.overlap = None self.q_g = [0, 0] # goal point of the robot heading to self.q_hit = [0, 0] # location where the robot first detect an obstacle self.boundary_following = False # tracking whether it is in boundary following mode self.m_line = None # m-line polygon self.trans_matrix = mat( [[0, 1], [-1, 0]] ) # transformation matrix for find the normal to the vector connecting a point on the obstacle to the robot self.q_hit_count = 0 self.q_hit_Thres = 1000 self.prev_follow = [[], []] ## Construct robot polygon (for checking overlap) pose = self.pose_handler.getPose() self.prev_pose = pose self.robot = PolyShapes.Rectangle(self.boxHorizontal, self.boxVertical) self.robot.shift(pose[0] - self.boxHorizontal_shift, pose[1] - self.boxVertical_shift) self.robot = PolyShapes.Circle(self.obsRange, (pose[0], pose[1])) - self.robot self.robot.rotate(pose[2] - pi / 2, pose[0], pose[1]) self.robot.shift(self.shift * cos(pose[2]), self.shift * sin(pose[2])) #construct real robot polygon( see if there is overlaping with path to goal self.realRobot = PolyShapes.Rectangle(self.boxRealHorizontal, self.boxRealVertical) self.realRobot.shift(pose[0] - self.boxRealHorizontal_shift, pose[1] - self.boxRealVertical_shift) self.realRobot.rotate(pose[2] - pi / 2, pose[0], pose[1]) #constructing polygon of different regions (holes being taken care) for region in self.proj.rfi.regions: self.map[region.name] = self.createRegionPolygon(region) for n in range(len(region.holeList)): # no of holes self.map[region.name] -= self.createRegionPolygon(region, n) #construct a polygon that included all the regions for regionName, regionPoly in self.map.iteritems(): self.all += regionPoly #setting for plotting if self.operate_system == 1: if self.PLOT or self.PLOT_OVERLAP == True: self.original_figure = 1 plt.figure(self.original_figure) if self.PLOT_EXIT or self.PLOT_M_LINE == True: self.overlap_figure = 2 plt.figure(self.overlap_figure) else: if self.PLOT_WINDOWS == True: # start using anmination to plot Pioneer self.fig = plt.figure() self.ax = self.fig.add_subplot(111) self.scope = _Scope(self.ax, self) thread.start_new_thread(self.jplot, ()) #Plot the robot on the map in figure 1 if self.PLOT == True: plt.figure(self.original_figure) plt.clf() self.plotPoly(self.realRobot, 'r') self.plotPoly(self.robot, 'b') plt.plot(pose[0], pose[1], 'bo') self.plotPioneer(self.original_figure)
def gotoRegion(self, current_reg, next_reg, last=False): """ If ``last`` is True, we will move to the center of the destination region. Returns ``True`` if we've reached the destination region. """ q_gBundle = [[], []] # goal bundle q_overlap = [[], []] # overlapping points with robot range pose = self.pose_handler.getPose() # Find our current configuration #Plot the robot on the map in figure 1 if self.PLOT == True: plt.figure(self.original_figure) plt.clf() self.plotPoly(self.realRobot, 'r') self.plotPoly(self.robot, 'b') plt.plot(pose[0], pose[1], 'bo') self.plotPioneer(self.original_figure) if current_reg == next_reg and not last: # No need to move! self.drive_handler.setVelocity(0, 0) # So let's stop return False # Check if Vicon has cut out if math.isnan(pose[2]): print "no vicon pose" print "WARNING: No Vicon data! Pausing." #self.drive_handler.setVelocity(0, 0) # So let's stop time.sleep(1) return False ###This part is run when the robot goes to a new region, otherwise, the original map will be used. if not self.previous_current_reg == current_reg: #print 'getting into bug alogorithm' #clean up the previous self.map_work self.map_work = Polygon.Polygon() # NOTE: Information about region geometry can be found in self.proj.rfi.regions # create polygon list for regions other than the current_reg and the next_reg self.map_work += self.map[self.proj.rfi.regions[current_reg].name] self.map_work += self.map[self.proj.rfi.regions[next_reg].name] # building current polygon and destination polygon self.nextRegionPoly = self.map[ self.proj.rfi.regions[next_reg].name] self.currentRegionPoly = self.map[ self.proj.rfi.regions[current_reg].name] #set to zero velocity before finding the tranFace self.drive_handler.setVelocity(0, 0) if last: transFace = None else: print "Current reg is " + str( self.proj.rfi.regions[current_reg].name.lower()) print "Next reg is " + str( self.proj.rfi.regions[next_reg].name.lower()) for i in range( len(self.proj.rfi.transitions[current_reg][next_reg])): pointArray_transface = [ x for x in self.proj.rfi.transitions[current_reg] [next_reg][i] ] transFace = asarray( map(self.coordmap_map2lab, pointArray_transface)) bundle_x = (transFace[0, 0] + transFace[1, 0]) / 2 #mid-point coordinate x bundle_y = (transFace[0, 1] + transFace[1, 1]) / 2 #mid-point coordinate y q_gBundle = hstack((q_gBundle, vstack( (bundle_x, bundle_y)))) q_gBundle = q_gBundle.transpose() # Find the closest face to the current position max_magsq = 1000000 for tf in q_gBundle: magsq = (tf[0] - pose[0])**2 + (tf[1] - pose[1])**2 if magsq < max_magsq: connection = 0 tf = tf + (tf - asarray(self.currentRegionPoly.center( ))) / norm(tf - asarray(self.currentRegionPoly.center( ))) * 2.1 * self.PioneerLengthHalf if not self.nextRegionPoly.covers( PolyShapes.Circle(self.PioneerLengthHalf * 2, (tf[0], tf[1]))): tf = tf - (tf - asarray( self.currentRegionPoly.center())) / norm( tf - asarray(self.currentRegionPoly.center( ))) * 4.2 * self.PioneerLengthHalf if self.nextRegionPoly.covers( PolyShapes.Circle( self.PioneerLengthHalf * 2, (tf[0], tf[1]))): connection = 1 else: connection = 1 if connection == 1: pt1 = tf max_magsq = magsq transFace = 1 self.q_g[0] = pt1[0] self.q_g[1] = pt1[1] else: sample = False while not sample: self.q_g[0], self.q_g[ 1] = self.nextRegionPoly.sample( random.random) robo = PolyShapes.Circle( self.PioneerLengthHalf, (self.q_g[0], self.q_g[1])) if not bool(robo - self.nextRegionPoly): sample = True """ # Push the goal point to somewhere inside the next region to ensure the robot will get there.(CHECK!!) self.q_g = self.q_g+(self.q_g-asarray(self.currentRegionPoly.center()))/norm(self.q_g-asarray(self.currentRegionPoly.center()))*3*self.PioneerLengthHalf if not self.nextRegionPoly.isInside(self.q_g[0],self.q_g[1]): self.q_g = self.q_g-(self.q_g-asarray(self.currentRegionPoly.center()))/norm(self.q_g-asarray(self.currentRegionPoly.center()))*6*self.PioneerLengthHalf """ #plot exiting point if self.PLOT_EXIT == True: plt.figure(self.overlap_figure) plt.clf() plt.plot(q_gBundle[:, 0], q_gBundle[:, 1], 'ko') plt.plot(self.q_g[0], self.q_g[1], 'ro') plt.plot(pose[0], pose[1], 'bo') self.plotPioneer(self.overlap_figure, 0) if transFace is None: print "ERROR: Unable to find transition face between regions %s and %s. Please check the decomposition (try viewing projectname_decomposed.regions in RegionEditor or a text editor)." % ( self.proj.rfi.regions[current_reg].name, self.proj.rfi.regions[next_reg].name) ################################################## #######check whether obstacle is detected######### ################################################## #Update pose,update self.robot, self.realRobot orientation self.robot.shift(pose[0] - self.prev_pose[0], pose[1] - self.prev_pose[1]) self.realRobot.shift(pose[0] - self.prev_pose[0], pose[1] - self.prev_pose[1]) self.robot.rotate(pose[2] - self.prev_pose[2], pose[0], pose[1]) self.realRobot.rotate(pose[2] - self.prev_pose[2], pose[0], pose[1]) self.prev_pose = pose ############################ ########### STEP 1########## ############################ ##Check whether obsRange overlaps with obstacle or the boundary (overlap returns the part of robot not covered by the region # for real Pioneer robot if self.system == 1: # motion controller is not in boundary following mode if self.boundary_following == False: if self.robocomm.getReceiveObs() == False: overlap = self.robot - (self.map_work) else: overlap = self.robot - (self.map_work - self.robocomm.getObsPoly()) else: #TRUE # use a robot with full range all around it Robot = PolyShapes.Circle(self.obsRange, (pose[0], pose[1])) Robot.shift(self.shift * cos(pose[2]), self.shift * sin(pose[2])) if self.robocomm.getReceiveObs() == False: overlap = Robot - (self.map_work) else: overlap = Robot - (self.map_work - self.robocomm.getObsPoly()) # for ODE else: if self.boundary_following == False: overlap = self.robot - (self.map_work) else: #TRUE overlap = self.robot - (self.map_work) if self.boundary_following == False: if bool(overlap): ## overlap of obstacles #print "There MAYBE overlap~~ check connection to goal" # check whether the real robot or and path to goal overlap with the obstacle QGoalPoly = PolyShapes.Circle(self.PioneerLengthHalf, (self.q_g[0], self.q_g[1])) path = PolyUtils.convexHull(self.realRobot + QGoalPoly) if self.system == 1: if self.robocomm.getReceiveObs() == False: pathOverlap = path - (self.map_work) else: pathOverlap = path - (self.map_work - self.robocomm.getObsPoly()) else: pathOverlap = path - (self.map_work) if bool( pathOverlap ): # there is overlapping, go into bounding following mode #print "There IS overlap" self.q_hit = mat([pose[0], pose[1]]).T self.boundary_following = True #Generate m-line polygon QHitPoly = PolyShapes.Circle(self.PioneerLengthHalf / 4, (pose[0], pose[1])) QGoalPoly = PolyShapes.Circle(self.PioneerLengthHalf / 4, (self.q_g[0], self.q_g[1])) self.m_line = PolyUtils.convexHull(QHitPoly + QGoalPoly) #plot the first overlap if self.PLOT_M_LINE == True: plt.figure(self.overlap_figure) plt.clf() self.plotPoly(QHitPoly, 'k') self.plotPoly(QGoalPoly, 'k') self.plotPoly(overlap, 'g') self.plotPoly(self.m_line, 'b') plt.plot(pose[0], pose[1], 'bo') self.plotPioneer(self.overlap_figure, 0) else: ##head towards the q_goal if self.system == 1: if self.robocomm.getReceiveObs( ) == False: # wait for obstacles from Pioneer vx = 0 vy = 0 else: dis_cur = vstack((self.q_g[0], self.q_g[1])) - mat( [pose[0], pose[1]]).T vx = (dis_cur / norm(dis_cur) / 3)[0, 0] vy = (dis_cur / norm(dis_cur) / 3)[1, 0] else: dis_cur = vstack((self.q_g[0], self.q_g[1])) - mat( [pose[0], pose[1]]).T vx = (dis_cur / norm(dis_cur) / 3)[0, 0] vy = (dis_cur / norm(dis_cur) / 3)[1, 0] #print "no obstacles 2-ODE true" else: ##head towards the q_goal if self.system == 1: if self.robocomm.getReceiveObs( ) == False: # wait for obstacles from Pioneer vx = 0 vy = 0 else: dis_cur = vstack((self.q_g[0], self.q_g[1])) - mat( [pose[0], pose[1]]).T vx = (dis_cur / norm(dis_cur) / 3)[0, 0] vy = (dis_cur / norm(dis_cur) / 3)[1, 0] else: dis_cur = vstack( (self.q_g[0], self.q_g[1])) - mat([pose[0], pose[1]]).T vx = (dis_cur / norm(dis_cur) / 3)[0, 0] vy = (dis_cur / norm(dis_cur) / 3)[1, 0] #print "no obstacles 1-ODE true" if self.boundary_following == True: self.q_hit_count += 1 # finding the point to go normal to (closest overlapping point) j = 0 recheck = 0 while not bool(overlap): # cannot see the obstacle. Based on the location of the previous point blow up the range of the robot on the left or on the right j += 1 # finding whether the previous obstacle point is on the left side or the right side of the robot # angle = angle of the previous point from the x-axis of the field # omega = angle of the current Pioneer orientation from the x-axis of the field # cc = differnece between angle and omega ( < pi = previous point on the left of robot, else on the right of robot) x = self.prev_follow[0] - pose[0] y = self.prev_follow[1] - pose[1] angle = atan(y / x) # convert angle to 2pi if x > 0 and y > 0: angle = angle elif x < 0 and y > 0: angle = pi + angle elif x < 0 and y < 0: angle = pi + angle else: angle = 2 * pi + angle # convert pose to 2pi if pose[2] < 0: omega = (2 * pi + pose[2]) else: omega = pose[2] if omega > angle: cc = 2 * pi - (omega - angle) else: cc = angle - omega # on the left #if angle - omega > 0 and angle - omega < pi: if cc < pi: #print "on the left, angle: "+ str(angle) + " omega: "+ str(omega)+ " angle-omega: "+ str(angle-omega) Robot = PolyShapes.Rectangle(self.range * 2 * j, self.range * 2 * j) Robot.shift(pose[0] - self.range * j * 2, pose[1] - self.range * j) Robot.rotate(pose[2] - pi / 2, pose[0], pose[1]) # on the right else: #print "on the right, angle: "+ str(angle) + " omega: "+ str(omega)+ " angle-omega: "+ str(angle-omega) Robot = PolyShapes.Rectangle(self.range * 2 * j, self.range * 2 * j) Robot.shift(pose[0], pose[1] - self.range * j) Robot.rotate(pose[2] - pi / 2, pose[0], pose[1]) if self.system == 1: overlap = Robot - (self.map_work - self.robocomm.getObsPoly()) else: overlap = Robot - (self.map_work) #self.plotPoly(Robot, 'm',2) #determines as dynamic obstacles and can be go striaight to the goal point if j >= 2: dis_cur = vstack( (self.q_g[0], self.q_g[1])) - mat([pose[0], pose[1]]).T vx = (dis_cur / norm(dis_cur) / 3)[0, 0] vy = (dis_cur / norm(dis_cur) / 3)[1, 0] overlap = None self.overlap = overlap self.q_hit_count = 0 self.boundary_following = False self.m_line = None self.drive_handler.setVelocity(vx, vy, pose[2]) RobotPoly = PolyShapes.Circle(self.PioneerLengthHalf + 0.06, (pose[0], pose[1])) ###0.05 departed = not self.currentRegionPoly.overlaps( self.realRobot) #departed = not self.currentRegionPoly.overlaps(self.realRobot) and (not (self.nextRegionPoly.overlaps(self.realRobot) and not self.nextRegionPoly.covers(self.realRobot))) arrived = self.nextRegionPoly.covers(self.realRobot) return arrived ##extra box plotting in figure 1# if self.PLOT_OVERLAP == True: plt.figure(self.original_figure) plt.clf() self.plotPoly(self.realRobot, 'r') self.plotPoly(self.robot, 'b') self.plotPoly(overlap, 'g', 3) plt.plot(pose[0], pose[1], 'bo') self.plotPioneer(self.original_figure) # find the closest point on the obstacle to the robot overlap_len = len(overlap) for j in range(overlap_len): BoundPolyPoints = asarray(overlap[j]) for i in range(len(BoundPolyPoints) - 1): bundle_x = ( BoundPolyPoints[i, 0] + BoundPolyPoints[1 + i, 0]) / 2 #mid-point coordinate x bundle_y = ( BoundPolyPoints[i, 1] + BoundPolyPoints[1 + i, 1]) / 2 #mid-point coordinate y q_overlap = hstack((q_overlap, vstack( (bundle_x, bundle_y)))) bundle_x = (BoundPolyPoints[len(BoundPolyPoints) - 1, 0] + BoundPolyPoints[0, 0]) / 2 #mid-point coordinate x bundle_y = (BoundPolyPoints[len(BoundPolyPoints) - 1, 1] + BoundPolyPoints[0, 1]) / 2 #mid-point coordinate y q_overlap = hstack((q_overlap, vstack((bundle_x, bundle_y)))) q_overlap = q_overlap.transpose() pt = self.closest_pt([pose[0], pose[1]], vstack( (q_overlap, asarray(PolyUtils.pointList(overlap))))) self.prev_follow = pt #calculate the vector to follow the obstacle normal = mat([pose[0], pose[1]] - pt) #find the distance from the closest point distance = norm(normal) velocity = normal * self.trans_matrix vx = (velocity / norm(velocity) / 3)[0, 0] vy = (velocity / norm(velocity) / 3)[0, 1] # push or pull the robot towards the obstacle depending on whether the robot is close or far from the obstacle. turn = pi / 4 * (distance - 0.5 * self.obsRange) / ( self.obsRange ) ### change to 0.6 from 0.5 for more allowance in following corr_matrix = mat([[cos(turn), -sin(turn)], [sin(turn), cos(turn)]]) v = corr_matrix * mat([[vx], [vy]]) vx = v[0, 0] vy = v[1, 0] ##plotting overlap on figure 2 if self.PLOT_OVERLAP == True: plt.figure(self.overlap_figure) plt.clf() self.plotPoly(self.m_line, 'b') self.plotPoly(overlap, 'r') plt.plot(pt[0], pt[1], 'ro') plt.plot(pose[0], pose[1], 'bo') self.plotPioneer(self.overlap_figure, 0) ## conditions that the loop will end #for 11111 RobotPoly = PolyShapes.Circle(self.PioneerLengthHalf + 0.06, (pose[0], pose[1])) ####0.05 departed = not self.currentRegionPoly.overlaps(self.realRobot) #departed = not self.currentRegionPoly.overlaps(self.realRobot) and (not (self.nextRegionPoly.overlaps(self.realRobot) and not self.nextRegionPoly.covers(self.realRobot))) arrived = self.nextRegionPoly.covers(self.realRobot) #for 33333 reachMLine = self.m_line.overlaps(RobotPoly) # 1.reached the next region if arrived: self.boundary_following = False self.m_line = None self.q_hit_count = 0 print "arriving at the next region. Exit boundary following mode" vx = 0 vy = 0 """ # 2.q_hit is reencountered elif norm(self.q_hit-mat([pose[0],pose[1]]).T) < 0.05 and self.q_hit_count > self.q_hit_Thres: print "reencounter q_hit. cannot reach q_goal" vx = 0 vy = 0 """ # 3.m-line reencountered elif reachMLine: #print >>sys.__stdout__, "m-line overlaps RoboPoly, m-line" + str(norm(self.q_g-self.q_hit)-2*self.obsRange) + " distance: " + str(norm(self.q_g-mat([pose[0],pose[1]]).T)) if norm(self.q_g - mat([pose[0], pose[1]]).T ) < norm(self.q_g - self.q_hit) - 2 * self.obsRange: #print "m-line overlaps RoboPoly, m-line" + str(norm(self.q_g-self.q_hit)-2*self.obsRange) + " distance: " + str(norm(self.q_g-mat([pose[0],pose[1]]).T)) #print "leaving boundary following mode" self.boundary_following = False self.m_line = None self.q_hit_count = 0 leaving = False # turn the robot till it is facing the goal while not leaving: x = self.q_g[0] - self.pose_handler.getPose()[0] y = self.q_g[1] - self.pose_handler.getPose()[1] angle = atan(y / x) if x > 0 and y > 0: angle = angle elif x < 0 and y > 0: angle = pi + angle elif x < 0 and y < 0: angle = pi + angle else: angle = 2 * pi + angle if self.pose_handler.getPose()[2] < 0: omega = (2 * pi + self.pose_handler.getPose()[2]) #print >>sys.__stdout__,"omega<0: "+ str(omega) else: omega = self.pose_handler.getPose()[2] #print >>sys.__stdout__,"omega: "+ str(omega) if omega > angle: cc = 2 * pi - (omega - angle) else: cc = angle - omega # angle(goal point orientation) on the left of omega(robot orientation) #if angle - omega > 0 and angle - omega < pi: if cc < pi: #print>>sys.__stdout__, "turn left" vx, vy = self.turnLeft(cc) # on the right else: #print>>sys.__stdout__, "turn right" vx, vy = self.turnRight(2 * pi - cc) #print>>sys.__stdout__, "omega: "+ str(omega) + " angle: "+ str(angle) + " (omega-angle): " + str(omega-angle) self.drive_handler.setVelocity( vx, vy, self.pose_handler.getPose()[2]) if omega - angle < pi / 6 and omega - angle > -pi / 6: leaving = True #Check whether the robot can leave now (the robot has to be closer to the goal than when it is at q_hit to leave) QGoalPoly = PolyShapes.Circle(self.PioneerLengthHalf, (self.q_g[0], self.q_g[1])) path = PolyUtils.convexHull(self.realRobot + QGoalPoly) if self.system == 1: if self.robocomm.getReceiveObs() == False: pathOverlap = path - (self.map_work) else: pathOverlap = path - (self.map_work - self.robocomm.getObsPoly()) else: pathOverlap = path - (self.map_work) if not bool(pathOverlap): #print "There is NO MORE obstacles in front for now." # check if the robot is closer to the goal compared with q_hit if norm(self.q_hit - mat(self.q_g).T) > norm( mat([pose[0], pose[1]]).T - mat(self.q_g).T): #print "The robot is closer than the leaving point. The robot can leave" self.boundary_following = False self.m_line = None self.q_hit_count = 0 dis_cur = vstack( (self.q_g[0], self.q_g[1])) - mat([pose[0], pose[1]]).T vx = (dis_cur / norm(dis_cur) / 3)[0, 0] vy = (dis_cur / norm(dis_cur) / 3)[1, 0] else: lala = 1 #print "not leaving bug algorithm. difference(-farther) =" + str(norm(self.q_hit-mat(self.q_g).T) - norm(mat([pose[0],pose[1]]).T-mat(self.q_g).T)) """ # Pass this desired velocity on to the drive handler # Check if there are obstacles within 0.35m of the robot, if so, stop the robot if self.system == 1: if self.robocomm.getSTOP() == True: vx = 0 vy = 0 """ #vx = 0 #vy = 0 self.overlap = overlap self.drive_handler.setVelocity(vx, vy, pose[2]) # Set the current region as the previous current region(for checking whether the robot has arrived at the next region) self.previous_current_reg = current_reg # check whether robot has arrived at the next region RobotPoly = PolyShapes.Circle(self.PioneerLengthHalf + 0.06, (pose[0], pose[1])) ###0.05 #departed = not self.currentRegionPoly.overlaps(self.realRobot) and (not (self.nextRegionPoly.overlaps(self.realRobot) and not self.nextRegionPoly.covers(self.realRobot))) departed = not self.currentRegionPoly.overlaps(self.realRobot) arrived = self.nextRegionPoly.covers(self.realRobot) if arrived: self.q_hit_count = 0 self.boundary_following = False self.m_line = None if departed and ( not arrived) and (time.time() - self.last_warning) > 0.5: print "WARNING: Left current region but not in expected destination region" # Figure out what region we think we stumbled into for r in self.proj.rfi.regions: pointArray = [self.coordmap_map2lab(x) for x in r.getPoints()] vertices = mat(pointArray).T if is_inside([pose[0], pose[1]], vertices): #print "I think I'm in " + r.name #print pose break self.last_warning = time.time() return arrived
def processData(self, data): """ Save the data to the appropriate category for possible extraction. """ #print 'I GOT DATA',data,[0],data[1] # Check for valid data (not null or empty string) #print '**************NOTIFICATION***************',type(_RobotCommunicator.WALL_HEADER),type(data[0]) if data: #print '**************NOTIFICATION***************',type(_RobotCommunicator.WALL_HEADER),type(data[0]),_RobotCommunicator.WALL_HEADER==data[0] # Check header and assign data appropriately # TODO: Check length of data for validity #print 'Header',data[0] if data[0] == _RobotCommunicator.POSE_HEADER: self.pose = unpack(_RobotCommunicator.POSE_FORMAT, data[1:]) elif data[0] == _RobotCommunicator.SENSOR_HEADER: #for i in range(1, len(data)-1, 2): index = unpack('B', data[1]) value = unpack('?', data[2]) # Update old values or create new sensor-value pair self.sensors[index[0]] = value[0] #print 'in csharp: ',[index,value] elif data[0] == _RobotCommunicator.WAYPOINT_HEADER: self.waypoints = [] # Clear old waypoints for i in range(1, len(data) - 16, 16): x, y = unpack(_RobotCommunicator.WAYPOINT_FORMAT, data[i:i + 15]) self.waypoints.append((x, y)) elif data[0] == _RobotCommunicator.DIRECTION_HEADER: self.direction = unpack(_RobotCommunicator.DIRECTION_FORMAT, data[1:]) elif data[0] == _RobotCommunicator.ACTUATOR_HEADER: self.actuators = [ ] # Clear old actuator commands for i in range(1, len(data)-1): self.actuators.append( unpack(_RobotCommunicator.ACTUATOR_FORMAT, data[i])) elif data[0] == _RobotCommunicator.WALL_HEADER: self.walls = {} # Clear old wall entries index = unpack('B', data[1]) x1, y1, x2, y2 = unpack(_RobotCommunicator.WALL_FORMAT, data[2:34]) self.walls = (x1, y1, x2, y2) #print '**************Coordinates***************',(x1,y1,x2,y2) print '****self.walls*********', self.walls elif data[0] == _RobotCommunicator.OBS_HEADER: index = unpack('B', data[1]) add, x1, y1 = unpack(_RobotCommunicator.OBS_FORMAT, data[2:26]) #print '***********self.obs*************'+','.join(map(str,[add,x1,y1])) self.obs = [add, x1, round(y1, 2)] if add == 1: a = PolyShapes.Rectangle(self.resolX, self.resolY) a.shift(x1, y1) self.obsPoly += a self.receiveObs = True #print "add obstacle:" + str(x1) + ","+ str(y1) elif add == 4: if x1 == 0: self.STOP = True else: self.STOP = False else: a = PolyShapes.Rectangle(self.resolX, self.resolY) a.shift(x1, y1) self.obsPoly -= a self.receiveObs = True #print "del obstacle:"+ str(x1) + ","+ str(y1) else: print "Unexpected or corrupted data packet received."
def buildTree(p,theta,vert, R, system, regionPoly,nextRegionPoly,q_gBundle,\ mappedRegions,allRegions,max_angle_allowed, plotting, operate_system,ax, last=False): """ This function builds the RRT tree pose: x,y position of the robot theta: current orientation of the robot R: radius of the robot system: determine step_size and radius for the example regionPoly: current region polygon nextRegionPoly: next region polygon q_gBundle: coordinates of q_goals that the robot can reach mappedRegions: region polygons allRegions: polygon that includes all the region max_angle_allowed: the difference in angle between the two nodes allowed (between 0 to 2*pi) plotting: 1 if plotting is enabled, 0- disabled operate_system: Which operating system is used for execution. Ubuntu and Mac is 1, Windows is 2 ax: plot for windows """ max_angle = max_angle_allowed """ if operate_system == 2: # start using anmination to plot Pioneer self.fig = plt.figure() self.ax = self.fig.add_subplot(111) self.scope = _Scope(self.ax,self) thread.start_new_thread(self.jplot,()) """ ## 1: Nao ; 2: STAGE ; 3: ODE if system == 1: ## Nao step_size = 0.2 #set the step_size for points be 1/5 of the norm from ORIGINAL = 0.4 elif system == 2: step_size = 0.5 elif system == 3: step_size = 15 if system == 1: ## Nao timeStep = 5 #time step for calculation of x, y position elif system == 2: timeStep = 4 #time step for calculation of x, y position elif system == 3: timeStep = 10 #time step for calculation of x, y position #10 #############tune velocity OMEGA, TIME STEP #fix velocity ## 1: Nao ; 2: STAGE ; 3: ODE if system == 1: ## Nao velocity = 0.05 #set the step_size for points be 1/5 of the norm from elif system == 2: velocity = 0.06 elif system == 3: velocity = 2 # what is used in RRTControllerHelper.setVelocity #1.5 #############tune velocity OMEGA, TIME STEP BoundPoly = regionPoly # Boundary polygon = current region polygon radius = R q_init = mat(p).T V = vstack((0, q_init)) V_theta = array([theta]) original_figure = 1 #!!! CONTROL SPACE: generate a list of omega for random sampling omegaLowerBound = -math.pi / 20 # upper bound for the value of omega omegaUpperBound = math.pi / 20 # lower bound for the value of omega omegaStepSize = 20 omega_range = linspace(omegaLowerBound, omegaUpperBound, omegaStepSize) omega_range_abso = linspace(omegaLowerBound * 4, omegaUpperBound * 4, omegaStepSize * 4) # range used when stuck > stuck_thres edgeX = [] edgeY = [] # check faces of the current region for goal points E = [[], []] Other = [[], []] path = 0 # if path formed then = 1 stuck = 0 # count for changing the range of sampling omega stuck_thres = 300 # threshold for changing the range of sampling omega if not plt.isinteractive(): plt.ion() plt.hold(True) while path == 0: #step -1: try connection to q_goal (generate path to goal) goalCheck = 0 i = 0 # pushing possible q_goals into the current region (ensure path is covered by the current region polygon) q_pass = [[], [], []] q_pass_dist = [] q_gBundle = mat(q_gBundle) while i < q_gBundle.shape[1]: ###not sure about shape q_g = q_gBundle[:, i] + (q_gBundle[:, i] - V[1:, ( shape(V)[1] - 1)]) / norm(q_gBundle[:, i] - V[1:, ( shape(V)[1] - 1)]) * radius ##original 2*radius trial = 1 if not BoundPoly.isInside(q_g[0], q_g[1]): trial = 2 q_g = q_gBundle[:, i] - (q_gBundle[:, i] - V[1:, ( shape(V)[1] - 1)]) / norm(q_gBundle[:, i] - V[1:, ( shape(V)[1] - 1)]) * radius ##original 2*radius #forming polygon for path checking cross_goal = cross( vstack((q_g - vstack( (V[1, shape(V)[1] - 1], V[2, shape(V)[1] - 1])), 0)).T, hstack((0, 0, 1))) cross_goal = cross_goal.T move_vector_goal = radius * cross_goal[0:2] / sqrt( (cross_goal[0, 0]**2 + cross_goal[1, 0]**2)) upperEdgeG = hstack((vstack( (V[1, shape(V)[1] - 1], V[2, shape(V)[1] - 1])), q_g)) + hstack( (move_vector_goal, move_vector_goal)) lowerEdgeG = hstack((vstack( (V[1, shape(V)[1] - 1], V[2, shape(V)[1] - 1])), q_g)) - hstack( (move_vector_goal, move_vector_goal)) EdgePolyGoal = Polygon.Polygon( (tuple(array(lowerEdgeG[:, 0].T)[0]), tuple(array(upperEdgeG[:, 0].T)[0]), tuple(array(upperEdgeG[:, 1].T)[0]), tuple(array(lowerEdgeG[:, 1].T)[0]))) dist = norm(q_g - V[1:, shape(V)[1] - 1]) connect_goal = BoundPoly.covers( EdgePolyGoal) #check coverage of path from new point to goal #check connection to goal """ if connect_goal: print "connection is true" path = 1 q_pass = hstack((q_pass,vstack((i,q_g)))) q_pass_dist = hstack((q_pass_dist,dist)) """ # compare orientation difference thetaPrev = V_theta[shape(V)[1] - 1] theta_orientation = abs( arctan((q_g[1, 0] - V[2, shape(V)[1] - 1]) / (q_g[0, 0] - V[1, shape(V)[1] - 1]))) if thetaPrev < 0: if q_g[1, 0] > V[2, shape(V)[1] - 1]: if q_g[0, 0] < V[1, shape(V)[1] - 1]: # second quadrant theta_orientation = -2 * pi + theta_orientation elif q_g[0, 0] > V[1, shape(V)[1] - 1]: # first quadrant theta_orientation = -pi - theta_orientation elif q_g[1, 0] < V[2, shape(V)[1] - 1]: if q_g[0, 0] < V[1, shape(V)[1] - 1]: #third quadrant theta_orientation = -pi + theta_orientation elif q_g[0, 0] > V[1, shape(V)[1] - 1]: # foruth quadrant theta_orientation = -theta_orientation else: if q_g[1, 0] > V[2, shape(V)[1] - 1]: if q_g[0, 0] < V[1, shape(V)[1] - 1]: # second quadrant theta_orientation = pi - theta_orientation elif q_g[0, 0] > V[1, shape(V)[1] - 1]: # first quadrant theta_orientation = theta_orientation elif q_g[1, 0] < V[2, shape(V)[1] - 1]: if q_g[0, 0] < V[1, shape(V)[1] - 1]: #third quadrant theta_orientation = pi + theta_orientation elif q_g[0, 0] > V[1, shape(V)[1] - 1]: # foruth quadrant theta_orientation = 2 * pi - theta_orientation ################################## PRINT PLT ################# if connect_goal: if plotting == True: if operate_system == 1: plt.suptitle('Randomly-exploring rapid tree', fontsize=12) BoundPolyPoints = asarray( PolyUtils.pointList(BoundPoly)) plt.plot(BoundPolyPoints[:, 0], BoundPolyPoints[:, 1], 'k') plt.xlabel('x') plt.ylabel('y') if shape(V)[1] <= 2: plt.plot((V[1, shape(V)[1] - 1], q_g[0, 0]), (V[2, shape(V)[1] - 1], q_g[1, 0]), 'b') else: plt.plot((V[1, E[0, shape(E)[1] - 1]], V[1, shape(V)[1] - 1], q_g[0, 0]), (V[2, E[0, shape(E)[1] - 1]], V[2, shape(V)[1] - 1], q_g[1, 0]), 'b') plt.figure(original_figure).canvas.draw() else: ax.suptitle('Randomly-exploring rapid tree', fontsize=12) BoundPolyPoints = asarray( PolyUtils.pointList(BoundPoly)) ax.plot(BoundPolyPoints[:, 0], BoundPolyPoints[:, 1], 'k') ax.xlabel('x') ax.ylabel('y') if shape(V)[1] <= 2: ax.plot((V[1, shape(V)[1] - 1], q_g[0, 0]), (V[2, shape(V)[1] - 1], q_g[1, 0]), 'b') else: ax.plot((V[1, E[0, shape(E)[1] - 1]], V[1, shape(V)[1] - 1], q_g[0, 0]), (V[2, E[0, shape(E)[1] - 1]], V[2, shape(V)[1] - 1], q_g[1, 0]), 'b') if connect_goal and abs(theta_orientation - thetaPrev) < max_angle: #if connect_goal and abs(theta_orientation - thetaPrev) < pi/3: print "connection is true.Path = 1" path = 1 q_pass = hstack((q_pass, vstack((i, q_g)))) q_pass_dist = hstack((q_pass_dist, dist)) i = i + 1 # connection to goal has established if path == 1: if shape(q_pass_dist)[0] == 1: cols = 0 else: (cols, ) = nonzero(q_pass_dist == min(q_pass_dist)) cols = asarray(cols)[0] q_g = q_pass[1:, cols] ###Catherine q_g = q_g - (q_gBundle[:, q_pass[0, cols]] - V[1:, (shape(V)[1] - 1)] ) / norm(q_gBundle[:, q_pass[0, cols]] - V[1:, (shape(V)[1] - 1)]) * 3 * radius #org 3 if not nextRegionPoly.isInside(q_g[0], q_g[1]): q_g = q_g + (q_gBundle[:, q_pass[0, cols]] - V[1:, (shape(V)[1] - 1)]) / norm( q_gBundle[:, q_pass[0, cols]] - V[1:, (shape(V)[1] - 1)]) * 6 * radius #org 3 if plotting == True: if operate_system == 1: plt.plot(q_g[0, 0], q_g[1, 0], 'ko') plt.figure(original_figure).canvas.draw() else: ax.plot(q_g[0, 0], q_g[1, 0], 'ko') numOfPoint = floor(norm(V[1:, shape(V)[1] - 1] - q_g) / step_size) if numOfPoint < 3: numOfPoint = 3 x = linspace(V[1, shape(V)[1] - 1], q_g[0, 0], numOfPoint) y = linspace(V[2, shape(V)[1] - 1], q_g[1, 0], numOfPoint) for i in range(x.shape[0]): if i != 0: V = hstack((V, vstack((shape(V)[1], x[i], y[i])))) E = hstack((E, vstack((shape(V)[1] - 2, shape(V)[1] - 1)))) # path is not formed, try to append points onto the tree if path == 0: success = 0 # whether adding a new point is successful hit_count = 0 # count for regenerating new edge with the same q_rand Icurrent = [ ] # to keep track of the index of the closest point to q_n while success == 0 and hit_count <= 2: if stuck > stuck_thres: omega = random.choice(omega_range_abso) else: #!!!! CONTROL SPACE STEP 1 - generate random omega omega = random.choice(omega_range) #!!!! CONTROL SPACE STEP 2 - pick a random point on the tree tree_index = random.choice(array(V[0])[0]) xPrev = V[1, tree_index] yPrev = V[2, tree_index] thetaPrev = V_theta[tree_index] j = 1 #!!!! CONTROL SPACE STEP 3 - Check path of the robot path_robot = PolyShapes.Circle(radius, (xPrev, yPrev)) while j <= timeStep: xOrg = xPrev yOrg = yPrev xPrev = xPrev + velocity / omega * ( sin(omega * 1 + thetaPrev) - sin(thetaPrev)) yPrev = yPrev - velocity / omega * ( cos(omega * 1 + thetaPrev) - cos(thetaPrev)) thetaPrev = omega * 1 + thetaPrev path_robot = path_robot + PolyShapes.Circle( radius, (xPrev, yPrev)) j = j + 1 path_all = PolyUtils.convexHull(path_robot) in_bound = BoundPoly.covers(path_all) # plotting plotPoly(path_all, 'r', 1) plotMap(original_figure, BoundPoly, allRegions) stuck = stuck + 1 if in_bound: stuck = stuck - 5 x = [] y = [] for k in PolyUtils.pointList(path_all): x = hstack((x, k[0])) y = hstack((y, k[1])) V = hstack((V, vstack((shape(V)[1], xPrev, yPrev)))) V_theta = hstack((V_theta, thetaPrev)) E = hstack((E, vstack((tree_index, shape(V)[1] - 1)))) Other = hstack((Other, vstack((velocity, omega)))) ##################### E should add omega and velocity success = 1 if finish_print == 1: print 'Here is the V matrix:', V, 'Here is the E matrix:', E print >> sys.__stdout__, 'Here is the V matrix:\n', V, '\nHere is the E matrix:\n', E #B: trim to a single path single = 0 while single == 0: trim = 0 for j in range(shape(V)[1] - 3): (row, col) = nonzero(E == j + 1) if len(col) == 1: E = delete(E, col[0], 1) trim = 1 if trim == 0: single = 1 # generate V to be sent to SimGUI to plot V_toPass = V[0:, 0] E_toPass = [[], []] for i in range(shape(E)[1]): V_toPass = hstack( (V_toPass, vstack((i, V[1, E[1, i - 1]], V[2, E[1, i - 1]])))) E_toPass = hstack((E_toPass, vstack((i - 1, i)))) ####print with matlib if plotting == True: if operate_system == 1: BoundPolyPoints = asarray(PolyUtils.pointList(BoundPoly)) plt.plot(BoundPolyPoints[:, 0], BoundPolyPoints[:, 1], 'k') plt.plot(V[1, :], V[2, :], 'b') for i in range(shape(E)[1] - 1): plt.text(V[1, E[0, i]], V[2, E[0, i]], V[0, E[0, i]], fontsize=12) plt.text(V[1, E[1, i]], V[2, E[1, i]], V[0, E[1, i]], fontsize=12) plt.figure(original_figure).canvas.draw() else: BoundPolyPoints = asarray(PolyUtils.pointList(BoundPoly)) ax.plot(BoundPolyPoints[:, 0], BoundPolyPoints[:, 1], 'k') ax.plot(V[1, :], V[2, :], 'b') for i in range(shape(E)[1] - 1): ax.text(V[1, E[0, i]], V[2, E[0, i]], V[0, E[0, i]], fontsize=12) ax.text(V[1, E[1, i]], V[2, E[1, i]], V[0, E[1, i]], fontsize=12) heading = E[0, 0] # parse string for RRT printing in GUI (in format: RRT:E[[1,2,3]]:V[[1,2,3]]) V = array(V) V_toPass = array(V_toPass) E_toPass = array(E_toPass) return V, E, heading, 0, V_toPass, E_toPass
def generateNewNode(self,V,V_theta,E,Other,regionPoly,stuck,append_after_latest_node =False): """ Generate a new node on the current tree matrix V : the node matrix V_theta : the orientation matrix E : the tree matrix (or edge matrix) Other : the matrix containing the velocity and angular velocity(omega) information regionPoly: the polygon of current region stuck : count on the number of times failed to generate new node append_after_latest_node : append new nodes to the latest node (True only if the previous node addition is successful) """ if self.system_print == True: print "In control space generating path,stuck = " + str(stuck) connection_to_tree = False # True when connection to the tree is successful if stuck > self.stuck_thres: # increase the range of omega since path cannot ge generated omega = random.choice(self.omega_range_escape) else: #!!!! CONTROL SPACE STEP 1 - generate random omega omega = random.choice(self.omega_range) #!!!! CONTROL SPACE STEP 2 - pick a random point on the tree if append_after_latest_node: tree_index = shape(V)[1]-1 else: if random.choice([1,2]) == 1: tree_index = random.choice(array(V[0])[0]) else: tree_index = shape(V)[1]-1 xPrev = V[1,tree_index] yPrev = V[2,tree_index] thetaPrev = V_theta[tree_index] j = 1 #!!!! CONTROL SPACE STEP 3 - Check path of the robot path_robot = PolyShapes.Circle(self.radius,(xPrev,yPrev)) while j <= self.timeStep: xOrg = xPrev yOrg = yPrev xPrev = xPrev + self.velocity/omega*(sin(omega* 1 + thetaPrev)-sin(thetaPrev)) yPrev = yPrev - self.velocity/omega*(cos(omega* 1 + thetaPrev)-cos(thetaPrev)) thetaPrev = omega* 1 + thetaPrev path_robot = path_robot + PolyShapes.Circle(self.radius,(xPrev,yPrev)) j = j + 1 thetaPrev = self.orientation_bound(thetaPrev) path_all = PolyUtils.convexHull(path_robot) in_bound = regionPoly.covers(path_all) # plotting if self.plotting == True: self.plotPoly(path_all,'r',1) stuck = stuck + 1 if in_bound: robot_new_node = PolyShapes.Circle(self.radius,(xPrev,yPrev)) # check how many nodes on the tree does the new node overlaps with nodes_overlap_count = 0 for k in range(shape(V)[1]-1): robot_old_node = PolyShapes.Circle(self.radius,(V[1,k],V[2,k])) if robot_new_node.overlaps(robot_old_node): if abs(thetaPrev - V_theta[k]) < self.max_angle_overlap: nodes_overlap_count += 1 if nodes_overlap_count == 0 or (stuck > self.stuck_thres+1 and nodes_overlap_count < 2) or (stuck > self.stuck_thres+500): if stuck > self.stuck_thres+1: append_after_latest_node = False if (stuck > self.stuck_thres+500): stuck = 0 stuck = stuck - 20 # plotting if self.plotting == True: self.plotPoly(path_all,'b',1) if self.system_print == True: print "node connected" V = hstack((V,vstack((shape(V)[1],xPrev,yPrev)))) V_theta = hstack((V_theta,thetaPrev)) E = hstack((E,vstack((tree_index ,shape(V)[1]-1)))) Other = hstack((Other,vstack((self.velocity,omega)))) ##################### E should add omega and velocity connection_to_tree = True append_after_latest_node = True else: append_after_latest_node = False if self.system_print == True: print "node not connected. check goal point" else: append_after_latest_node = False return V,V_theta,E,Other,stuck,append_after_latest_node, connection_to_tree
def buildTree(self,p,theta,regionPoly,nextRegionPoly,q_gBundle,face_normal, last=False): """ This function builds the RRT tree. p : x,y position of the robot theta : current orientation of the robot regionPoly : current region polygon nextRegionPoly : next region polygon q_gBundle : coordinates of q_goals that the robot can reach face_normal : the normal vector of each face corresponding to each goal point in q_gBundle """ q_init = mat(p).T V = vstack((0,q_init)) theta = self.orientation_bound(theta) V_theta = array([theta]) #!!! CONTROL SPACE: generate a list of omega for random sampling omegaLowerBound = -math.pi/20 # upper bound for the value of omega omegaUpperBound = math.pi/20 # lower bound for the value of omega omegaNoOfSteps = 20 self.omega_range = linspace(omegaLowerBound,omegaUpperBound,omegaNoOfSteps) self.omega_range_escape = linspace(omegaLowerBound*4,omegaUpperBound*4,omegaNoOfSteps*4) # range used when stuck > stuck_thres regionPolyOld = Polygon.Polygon(regionPoly) #regionPoly += PolyShapes.Circle(self.radius*2.5,(q_init[0,0],q_init[1,0])) regionPoly += PolyShapes.Circle(self.radius*4,(q_init[0,0],q_init[1,0])) # check faces of the current region for goal points E = [[],[]] # the tree matrix Other = [[],[]] path = False # if path formed then = 1 stuck = 0 # count for changing the range of sampling omega append_after_latest_node = False # append new nodes to the latest node if self.system_print == True: print "plotting in buildTree is " + str(self.plotting) if self.plotting == True: if not plt.isinteractive(): plt.ion() plt.hold(True) while not path: #step -1: try connection to q_goal (generate path to goal) i = 0 ltlmop_logger.debug("finding RRT Path...") if self.system_print == True: print "Try Connection to the goal points" # pushing possible q_goals into the current region (ensure path is covered by the current region polygon) q_pass = [[],[],[]] q_pass_dist = [] q_gBundle = mat(q_gBundle) face_normal = mat(face_normal) while i < q_gBundle.shape[1]: q_g_original = q_gBundle[:,i] q_g = q_gBundle[:,i]+face_normal[:,i]*1.5*self.radius ##original 2*self.radius #q_g = q_gBundle[:,i]+(q_gBundle[:,i]-V[1:,(shape(V)[1]-1)])/norm(q_gBundle[:,i]-V[1:,(shape(V)[1]-1)])*1.5*self.radius ##original 2*self.radius if not regionPolyOld.isInside(q_g[0],q_g[1]): #q_g = q_gBundle[:,i]-(q_gBundle[:,i]-V[1:,(shape(V)[1]-1)])/norm(q_gBundle[:,i]-V[1:,(shape(V)[1]-1)])*1.5*self.radius ##original 2*self.radius q_g = q_gBundle[:,i]-face_normal[:,i]*1.5*self.radius ##original 2*self.radius #forming polygon for path checking EdgePolyGoal = PolyShapes.Circle(self.radius,(q_g[0,0],q_g[1,0])) + PolyShapes.Circle(self.radius,(V[1,shape(V)[1]-1],V[2:,shape(V)[1]-1])) EdgePolyGoal = PolyUtils.convexHull(EdgePolyGoal) dist = norm(q_g - V[1:,shape(V)[1]-1]) #check connection to goal connect_goal = regionPoly.covers(EdgePolyGoal) #check coverage of path from new point to goal # compare orientation difference thetaPrev = V_theta[shape(V)[1]-1] if not (q_g[0,0]- V[1,shape(V)[1]-1]) == 0: theta_orientation = abs(arctan((q_g[1,0]- V[2,shape(V)[1]-1])/(q_g[0,0]- V[1,shape(V)[1]-1]))) else: theta_orientation = 0 if q_g[1,0] > V[2,shape(V)[1]-1]: if q_g[0,0] < V[1,shape(V)[1]-1]: # second quadrant theta_orientation = pi - theta_orientation elif q_g[0,0] > V[1,shape(V)[1]-1]: # first quadrant theta_orientation = theta_orientation elif q_g[1,0] < V[2,shape(V)[1]-1]: if q_g[0,0] < V[1,shape(V)[1]-1]: #third quadrant theta_orientation = pi + theta_orientation elif q_g[0,0] > V[1,shape(V)[1]-1]: # foruth quadrant theta_orientation = 2*pi - theta_orientation # check the angle between vector(new goal to goal_original ) and vector( latest node to new goal) Goal_to_GoalOriginal = q_g_original - q_g LatestNode_to_Goal = q_g - V[1:,shape(V)[1]-1] Angle_Goal_LatestNode= arccos(vdot(array(Goal_to_GoalOriginal), array(LatestNode_to_Goal))/norm(Goal_to_GoalOriginal)/norm(LatestNode_to_Goal)) # if connection to goal can be established and the max change in orientation of the robot is smaller than max_angle, tree is said to be completed. if self.orientation_print == True: print "theta_orientation is " + str(theta_orientation) print "thetaPrev is " + str(thetaPrev) print "(theta_orientation - thetaPrev) is " + str(abs(theta_orientation - thetaPrev)) print "self.max_angle_allowed is " + str(self.max_angle_allowed) print "abs(theta_orientation - thetaPrev) < self.max_angle_allowed" + str(abs(theta_orientation - thetaPrev) < self.max_angle_allowed) print"Goal_to_GoalOriginal: " + str( array(Goal_to_GoalOriginal)) + "; LatestNode_to_Goal: " + str( array(LatestNode_to_Goal)) print vdot(array(Goal_to_GoalOriginal), array(LatestNode_to_Goal)) print "Angle_Goal_LatestNode" + str(Angle_Goal_LatestNode) if connect_goal and (abs(theta_orientation - thetaPrev) < self.max_angle_allowed) and (Angle_Goal_LatestNode < self.max_angle_allowed): path = True q_pass = hstack((q_pass,vstack((i,q_g)))) q_pass_dist = hstack((q_pass_dist,dist)) i = i + 1 if self.system_print == True: print "checked goal points" self.E = E self.V = V # connection to goal has established # Obtain the closest goal point that path can be formed. if path: if shape(q_pass_dist)[0] == 1: cols = 0 else: (cols,) = nonzero(q_pass_dist == min(q_pass_dist)) cols = asarray(cols)[0] q_g = q_pass[1:,cols] """ q_g = q_g-(q_gBundle[:,q_pass[0,cols]]-V[1:,(shape(V)[1]-1)])/norm(q_gBundle[:,q_pass[0,cols]]-V[1:,(shape(V)[1]-1)])*3*self.radius #org 3 if not nextRegionPoly.isInside(q_g[0],q_g[1]): q_g = q_g+(q_gBundle[:,q_pass[0,cols]]-V[1:,(shape(V)[1]-1)])/norm(q_gBundle[:,q_pass[0,cols]]-V[1:,(shape(V)[1]-1)])*6*self.radius #org 3 """ if self.plotting == True : if self.operate_system == 1: plt.suptitle('Rapidly-exploring Random Tree', fontsize=12) plt.xlabel('x') plt.ylabel('y') if shape(V)[1] <= 2: plt.plot(( V[1,shape(V)[1]-1],q_g[0,0]),( V[2,shape(V)[1]-1],q_g[1,0]),'b') else: plt.plot(( V[1,E[0,shape(E)[1]-1]], V[1,shape(V)[1]-1],q_g[0,0]),( V[2,E[0,shape(E)[1]-1]], V[2,shape(V)[1]-1],q_g[1,0]),'b') plt.plot(q_g[0,0],q_g[1,0],'ko') plt.figure(1).canvas.draw() plt.pause(0.0001) else: BoundPolyPoints = asarray(PolyUtils.pointList(regionPoly)) self.ax.plot(BoundPolyPoints[:,0],BoundPolyPoints[:,1],'k') if shape(V)[1] <= 2: self.ax.plot(( V[1,shape(V)[1]-1],q_g[0,0]),( V[2,shape(V)[1]-1],q_g[1,0]),'b') else: self.ax.plot(( V[1,E[0,shape(E)[1]-1]], V[1,shape(V)[1]-1],q_g[0,0]),( V[2,E[0,shape(E)[1]-1]], V[2,shape(V)[1]-1],q_g[1,0]),'b') self.ax.plot(q_g[0,0],q_g[1,0],'ko') # trim the path connecting current node to goal point into pieces if the path is too long now numOfPoint = floor(norm(V[1:,shape(V)[1]-1]- q_g)/self.step_size) if numOfPoint < 3: numOfPoint = 3 x = linspace( V[1,shape(V)[1]-1], q_g[0,0], numOfPoint ) y = linspace( V[2,shape(V)[1]-1], q_g[1,0], numOfPoint ) for i in range(x.shape[0]): if i != 0: V = hstack((V,vstack((shape(V)[1],x[i],y[i])))) E = hstack((E,vstack((shape(V)[1]-2,shape(V)[1]-1)))) #push the goal point to the next region if self.system == 1: q_g = q_g+face_normal[:,q_pass[0,cols]]*4*self.radius ##original 3*self.radius else: q_g = q_g+face_normal[:,q_pass[0,cols]]*3*self.radius ##original 3*self.radius if not nextRegionPoly.isInside(q_g[0],q_g[1]): if self.system == 1: q_g = q_g-face_normal[:,q_pass[0,cols]]*8*self.radius ##original 6*self.radius else: q_g = q_g-face_normal[:,q_pass[0,cols]]*6*self.radius ##original 6*self.radius V = hstack((V,vstack((shape(V)[1],q_g[0,0],q_g[1,0])))) E = hstack((E,vstack((shape(V)[1]-2 ,shape(V)[1]-1)))) if self.plotting == True : if self.operate_system == 1: plt.plot(q_g[0,0],q_g[1,0],'ko') plt.plot(( V[1,shape(V)[1]-1],V[1,shape(V)[1]-2]),( V[2,shape(V)[1]-1],V[2,shape(V)[1]-2]),'b') plt.figure(1).canvas.draw() plt.pause(0.0001) else: self.ax.plot(q_g[0,0],q_g[1,0],'ko') self.ax.plot(( V[1,shape(V)[1]-1],V[1,shape(V)[1]-2]),( V[2,shape(V)[1]-1],V[2,shape(V)[1]-2]),'b') # path is not formed, try to append points onto the tree if not path: # connection_to_tree : connection to the tree is successful if append_after_latest_node: V,V_theta,E,Other,stuck,append_after_latest_node, connection_to_tree = self.generateNewNode(V,V_theta,E,Other,regionPoly,stuck, append_after_latest_node) else: connection_to_tree = False while not connection_to_tree: V,V_theta,E,Other,stuck,append_after_latest_node, connection_to_tree = self.generateNewNode (V,V_theta,E,Other,regionPoly,stuck) if self.finish_print: print 'Here is the V matrix:', V, 'Here is the E matrix:',E print >>sys.__stdout__, 'Here is the V matrix:\n', V, '\nHere is the E matrix:\n',E #B: trim to a single path single = 0 while single == 0: trim = 0 for j in range(shape(V)[1]-3): (row,col) = nonzero(E == j+1) if len(col) == 1: E = delete(E, col[0], 1) trim = 1 if trim == 0: single = 1; ####print with matlib if self.plotting ==True : if self.operate_system == 1: plt.plot(V[1,:],V[2,:],'b') for i in range(shape(E)[1]): plt.text(V[1,E[0,i]],V[2,E[0,i]], V[0,E[0,i]], fontsize=12) plt.text(V[1,E[1,i]],V[2,E[1,i]], V[0,E[1,i]], fontsize=12) plt.figure(1).canvas.draw() plt.pause(0.0001) else: BoundPolyPoints = asarray(PolyUtils.pointList(regionPoly)) self.ax.plot(BoundPolyPoints[:,0],BoundPolyPoints[:,1],'k') self.ax.plot(V[1,:],V[2,:],'b') for i in range(shape(E)[1]): self.ax.text(V[1,E[0,i]],V[2,E[0,i]], V[0,E[0,i]], fontsize=12) self.ax.text(V[1,E[1,i]],V[2,E[1,i]], V[0,E[1,i]], fontsize=12) # plot in simGUI self.path = [] for i in range(shape(E)[1]): self.path.append(tuple(map(int, self.executor.hsub.coordmap_lab2map([V[1,E[0,i]],V[2,E[0,i]]])))) self.path.append(tuple(map(int, self.executor.hsub.coordmap_lab2map([V[1,E[1,i]],V[2,E[1,i]]])))) self.executor.postEvent("RRT", self.path) #return V, E, and the current node number on the tree V = array(V) return V, E, 0