コード例 #1
0
ファイル: knot_identification.py プロジェクト: amoliu/lfd
def compute_dt_code(ctl_pts, plotting=False):
    """Takes rope control points (Nx3 array), closes the loop, and computes the Dowker-Thistlethwaite code for the knot.
       The z-value for the points are used for determining over/undercrossings.
       Follows procedure outlined here: http://katlas.math.toronto.edu/wiki/DT_(Dowker-Thistlethwaite)_Codes
       """

    # First, close the loop by introducing extra points under the table and toward the robot (by subtracting z and x values)
    # first_pt, last_pt =  ctl_pts[0], ctl_pts[-1]
    # flipped = False
    # if first_pt[1] > last_pt[1]:
    #     first_pt, last_pt = last_pt, first_pt
    #     flipped = True
    # min_z = ctl_pts[:,2].min()
    # extra_first_pt, extra_last_pt = first_pt + [-.1, -.1, min_z-1], last_pt + [-.1, .1, min_z-1]
    # if flipped:
    #     extra_pts = [extra_first_pt, extra_first_pt + [-1, 0, 0], extra_last_pt + [-1, 0, 0], extra_last_pt, last_pt]
    # else:
    #     extra_pts = [extra_last_pt, extra_last_pt + [-1, 0, 0], extra_first_pt + [-1, 0, 0], extra_first_pt, first_pt]
    # ctl_pts = np.append(ctl_pts, extra_pts, axis=0)

    if plotting:
        import trajoptpy, openravepy
        env = openravepy.Environment()
        viewer = trajoptpy.GetViewer(env)
        handles = []
        handles.append(env.plot3(ctl_pts, 5, [0, 0, 1]))
        viewer.Idle()

    # Upsampling loop: upsample until every segment has at most one crossing
    need_upsample_ind = None
    upsample_iters = 0
    max_upsample_iters = 10
    while True:
        counter = 1
        crossings = defaultdict(list)
        # Walk along rope: for each segment, compute intersections with all other segments
        for i in range(len(ctl_pts) - 1):
            curr_seg = ctl_pts[i:i+2,:]
            intersections, ts, us = intersect_segs(ctl_pts[:,:2], curr_seg[:,:2])

            if len(intersections) == 0:
                continue
            if len(intersections) != 1:
                LOG.debug('warning: more than one intersection for segment %d, now upsampling', i)
                need_upsample_ind = i
                break

            # for each intersection, determine and record over/undercrossing
            i_int = intersections[0]
            if plotting:
                handles.append(env.drawlinestrip(ctl_pts[i_int:i_int+2], 5, [1, 0, 0]))
            int_point_rope = ctl_pts[i_int] + ts[i_int]*(ctl_pts[i_int+1] - ctl_pts[i_int])
            int_point_curr_seg = curr_seg[0] + us[i_int]*(curr_seg[1] - curr_seg[0])
            #assert np.allclose(int_point_rope[:2], int_point_curr_seg[:2])
            above = int_point_curr_seg[2] > int_point_rope[2]
            crossings[tuple(sorted((i, i_int)))].append(-counter if counter % 2 == 0 and above else counter)
            counter += 1
        if plotting: viewer.Idle()
        # upsample if necessary
        if need_upsample_ind is not None and upsample_iters < max_upsample_iters:
            spacing = np.linspace(0, 1, len(ctl_pts))
            new_spacing = np.insert(spacing, need_upsample_ind+1, (spacing[need_upsample_ind]+spacing[need_upsample_ind+1])/2.)
            ctl_pts = math_utils.interp2d(new_spacing, spacing, ctl_pts)
            upsample_iters += 1
            need_upsample = None
            continue
        break

    # Extract relevant part of crossing data to produce DT code
    out = []
    for pair in crossings.itervalues():
        assert len(pair) == 2
        odd = [p for p in pair if p % 2 == 1][0]
        even = [p for p in pair if p % 2 == 0][0]
        out.append((odd, even))
    out.sort()
    dt_code = [-o[1] for o in out]
    return dt_code
コード例 #2
0
ファイル: knot_identification.py プロジェクト: zzz622848/lfd
def compute_dt_code(ctl_pts, plotting=False):
    """Takes rope control points (Nx3 array), closes the loop, and computes the Dowker-Thistlethwaite code for the knot.
       The z-value for the points are used for determining over/undercrossings.
       Follows procedure outlined here: http://katlas.math.toronto.edu/wiki/DT_(Dowker-Thistlethwaite)_Codes
       """

    # First, close the loop by introducing extra points under the table and toward the robot (by subtracting z and x values)
    # first_pt, last_pt =  ctl_pts[0], ctl_pts[-1]
    # flipped = False
    # if first_pt[1] > last_pt[1]:
    #     first_pt, last_pt = last_pt, first_pt
    #     flipped = True
    # min_z = ctl_pts[:,2].min()
    # extra_first_pt, extra_last_pt = first_pt + [-.1, -.1, min_z-1], last_pt + [-.1, .1, min_z-1]
    # if flipped:
    #     extra_pts = [extra_first_pt, extra_first_pt + [-1, 0, 0], extra_last_pt + [-1, 0, 0], extra_last_pt, last_pt]
    # else:
    #     extra_pts = [extra_last_pt, extra_last_pt + [-1, 0, 0], extra_first_pt + [-1, 0, 0], extra_first_pt, first_pt]
    # ctl_pts = np.append(ctl_pts, extra_pts, axis=0)

    if plotting:
        import trajoptpy, openravepy
        env = openravepy.Environment()
        viewer = trajoptpy.GetViewer(env)
        handles = []
        handles.append(env.plot3(ctl_pts, 5, [0, 0, 1]))
        viewer.Idle()

    # Upsampling loop: upsample until every segment has at most one crossing
    need_upsample_ind = None
    upsample_iters = 0
    max_upsample_iters = 10
    while True:
        counter = 1
        crossings = defaultdict(list)
        # Walk along rope: for each segment, compute intersections with all other segments
        for i in range(len(ctl_pts) - 1):
            curr_seg = ctl_pts[i:i + 2, :]
            intersections, ts, us = intersect_segs(ctl_pts[:, :2],
                                                   curr_seg[:, :2])

            if len(intersections) == 0:
                continue
            if len(intersections) != 1:
                LOG.debug(
                    'warning: more than one intersection for segment %d, now upsampling',
                    i)
                need_upsample_ind = i
                break

            # for each intersection, determine and record over/undercrossing
            i_int = intersections[0]
            if plotting:
                handles.append(
                    env.drawlinestrip(ctl_pts[i_int:i_int + 2], 5, [1, 0, 0]))
            int_point_rope = ctl_pts[i_int] + ts[i_int] * (ctl_pts[i_int + 1] -
                                                           ctl_pts[i_int])
            int_point_curr_seg = curr_seg[0] + us[i_int] * (curr_seg[1] -
                                                            curr_seg[0])
            #assert np.allclose(int_point_rope[:2], int_point_curr_seg[:2])
            above = int_point_curr_seg[2] > int_point_rope[2]
            crossings[tuple(sorted(
                (i, i_int)))].append(-counter if counter %
                                     2 == 0 and above else counter)
            counter += 1
        if plotting: viewer.Idle()
        # upsample if necessary
        if need_upsample_ind is not None and upsample_iters < max_upsample_iters:
            spacing = np.linspace(0, 1, len(ctl_pts))
            new_spacing = np.insert(
                spacing, need_upsample_ind + 1,
                (spacing[need_upsample_ind] + spacing[need_upsample_ind + 1]) /
                2.)
            ctl_pts = math_utils.interp2d(new_spacing, spacing, ctl_pts)
            upsample_iters += 1
            need_upsample = None
            continue
        break

    # Extract relevant part of crossing data to produce DT code
    out = []
    for pair in crossings.itervalues():
        assert len(pair) == 2
        odd = [p for p in pair if p % 2 == 1][0]
        even = [p for p in pair if p % 2 == 0][0]
        out.append((odd, even))
    out.sort()
    dt_code = [-o[1] for o in out]
    return dt_code