Пример #1
0
 def fit_line(self, scan, start_index, end_index, maximum_range):
     
     # First we must calculate alpha, using the formula presented in the
     # course notes (due to Arras, 1998).
     sumWeights = 0
     sumNumL = 0 # The summation term in the numerator on the left
     sumNumR = 0 # The summation term in the numerator on the right
     sumDenL = 0 # The summation term in the denominator on the left
     sumDenR = 0 # The summation term in the denominator on the rt.
     for i in range(start_index, end_index+1):  
         rho = scan[i]
         if rho == 0 or rho > maximum_range:
             continue
         theta = black_board.angle_min + i * black_board.angle_increment
         weight = 1 / rho**2
         #weight = 1
         sumWeights += weight
 
         factor1 = weight * rho * rho
         sumNumL += factor1 * math.sin(2 * theta)
         sumDenL += factor1 * math.cos(2 * theta)
         
         for j in range(start_index, end_index+1):
             rho_j = scan[j]
             if rho_j == 0 or rho_j > maximum_range:
                 continue
             theta_j = black_board.angle_min + j * black_board.angle_increment
             weight_j = 1 / rho_j**2
             #weight_j = 1
 
             factor2 = weight * weight_j * rho * rho_j
             sumNumR += factor2 * math.cos(theta) * math.sin(theta_j)
             sumDenR += factor2 * math.cos(theta + theta_j)
 
     if sumWeights == 0:
         # There are either no scan points at all, or none within range.
         return None
 
     sumNumR *= 2.0 / sumWeights
     sumDenR /= sumWeights
     alpha = math.atan2(sumNumL - sumNumR, sumDenL - sumDenR) / 2.0 + math.pi/2
 
     # We now calculate r.
     sumNum = 0 # The summation term in the numerator
     for i in range(start_index, end_index+1):
         rho = scan[i]
         if rho == 0 or rho > maximum_range:
             continue
         theta = black_board.angle_min + i * black_board.angle_increment
         weight = 1 / rho**2
         #weight = 1
 
         sumNum += weight * rho * math.cos(theta - alpha)
 
     r = sumNum / sumWeights
 
     # It is possible that the r value returned above is negative.  We formulate
     # r as a positive quantity, but the optimization process doesn't know about
     # this.  Having a negative r can create problems down the road (e.g. for
     # line-based wall following).  So we flip our parameters to make r positive.
     if r < 0:
         r *= -1
         alpha += math.pi
 
     # Make sure that alpha is in the range (-pi, pi].
     alpha = constrain_angle(alpha)
 
     # Determine the first and last points used to estimate this line's
     # parameters.  These two points do not define the line, but they are useful
     #pdb.set_trace()
     # for visualization to show the range of points involved.
     firstScanPoint = Point32()
     lastScanPoint = Point32()
     dist = scan[start_index]
     angle = black_board.angle_min + start_index * black_board.angle_increment
     if dist <= maximum_range:
         firstScanPoint.x = dist * math.cos(angle)
         firstScanPoint.y = dist * math.sin(angle)
     dist = scan[end_index]
     angle = black_board.angle_min + end_index * black_board.angle_increment
     if dist <= maximum_range:
         lastScanPoint.x = dist * math.cos(angle)
         lastScanPoint.y = dist * math.sin(angle)
     
     return ExtractedLine(r, alpha, firstScanPoint, lastScanPoint)
Пример #2
0
def fit_line(scan, start_index, end_index, maximum_range):
    """ 
    Fit a line to the given LaserScan yielding an ExtractedLine.
    
    The method of weighted least squares is applied to yield a description of
    the line consisting of the tuple (r, alpha) where 'r' is the orthogonal
    distance of the line to the origin and 'alpha' is the angle that the ray
    perpendicular to the line makes with the origin.  Weighted least squares is
    applied as described in "Introduction to Autonomous Mobile Robots" by
    Siegwart, Nourbakhsh, and Scaramuzza.

    Arguments:
    start_index -- index of the first data point to be used in the line fitting
                   procedure.
    end_index -- index of the last data point to be used in the line fitting
                 procedure.
    maximum_range -- specifies the maximum range of data points which will be
                     incorporated into the fitted line.

    If the scan is empty or there are no points within 'maximum_range' then
    None is returned.
    """

    # First we must calculate alpha, using the formula presented in the
    # course notes (due to Arras, 1998).
    sumWeights = 0
    sumNumL = 0  # The summation term in the numerator on the left
    sumNumR = 0  # The summation term in the numerator on the right
    sumDenL = 0  # The summation term in the denominator on the left
    sumDenR = 0  # The summation term in the denominator on the rt.
    for i in range(start_index, end_index + 1):

        rho = scan.ranges[i]
        if rho == 0 or rho > maximum_range:
            continue
        theta = scan.angle_min + i * scan.angle_increment
        weight = 1 / rho**2
        #weight = 1

        sumWeights += weight

        factor1 = weight * rho * rho
        sumNumL += factor1 * sin(2 * theta)
        sumDenL += factor1 * cos(2 * theta)

        for j in range(start_index, end_index + 1):
            rho_j = scan.ranges[j]
            if rho_j == 0 or rho_j > maximum_range:
                continue
            theta_j = scan.angle_min + j * scan.angle_increment
            weight_j = 1 / rho_j**2
            #weight_j = 1

            factor2 = weight * weight_j * rho * rho_j
            sumNumR += factor2 * cos(theta) * sin(theta_j)
            sumDenR += factor2 * cos(theta + theta_j)

    if sumWeights == 0:
        # There are either no scan points at all, or none within range.
        return None

    sumNumR *= 2.0 / sumWeights
    sumDenR /= sumWeights
    alpha = atan2(sumNumL - sumNumR, sumDenL - sumDenR) / 2.0 + pi / 2

    # We now calculate r.
    sumNum = 0  # The summation term in the numerator
    for i in range(start_index, end_index + 1):
        rho = scan.ranges[i]
        if rho == 0 or rho > maximum_range:
            continue
        theta = scan.angle_min + i * scan.angle_increment
        weight = 1 / rho**2
        #weight = 1

        sumNum += weight * rho * cos(theta - alpha)

    r = sumNum / sumWeights

    # It is possible that the r value returned above is negative.  We formulate
    # r as a positive quantity, but the optimization process doesn't know about
    # this.  Having a negative r can create problems down the road (e.g. for
    # line-based wall following).  So we flip our parameters to make r positive.
    if r < 0:
        r *= -1
        alpha += pi

    # Make sure that alpha is in the range (-pi, pi].
    alpha = constrain_angle(alpha)

    # Determine the first and last points used to estimate this line's
    # parameters.  These two points do not define the line, but they are useful
    # for visualization to show the range of points involved.
    firstScanPoint = Point32()
    lastScanPoint = Point32()
    dist = scan.ranges[start_index]
    angle = scan.angle_min + start_index * scan.angle_increment
    if dist <= maximum_range:
        firstScanPoint.x = dist * cos(angle)
        firstScanPoint.y = dist * sin(angle)
    dist = scan.ranges[end_index]
    angle = scan.angle_min + end_index * scan.angle_increment
    if dist <= maximum_range:
        lastScanPoint.x = dist * cos(angle)
        lastScanPoint.y = dist * sin(angle)

    return ExtractedLine(r, alpha, firstScanPoint, lastScanPoint)