def PublishSpace(self, bb, sensor,algorithm, aux_payload):
        planes = self.GenPlanes(bb)
        if len(planes) == 0:
            print "WARNING: Camera2BoundingBox:PublishSpace(): Returning None because len(planes) == 0"
            return None

        space = Convex_Space()

        space.planes      = planes
        space.sensor      = sensor
        space.algorithm   = algorithm
        space.aux_payload = aux_payload

        self.publisher.publish(space)

        # some callers might be interested in seeing what I just published
        return space
    def PublishCroppedPyramid(self, polygonStamped, front):
        # PERFORMANCE WARNING: I'm guessing that calling transformPoint()
        # over and over is going to have to lots of painful lookups, and
        # performance will suck.  But for now, I'm focusing on correctness
        # rather than speed, so I'm calling their API rather than getting
        # the transform for myself with lookupTransform().

    	self.tf_name = polygonStamped.header.frame_id
    	points = polygonStamped.polygon.points

        # abort (with warning) if we don't yet know the position of the
        # camera.
        if not self.tf_listener.canTransform(self.tf_name, "/map", polygonStamped.header.stamp):
            print "WARNING: Could not find the tf for the camera %s" % self.tf_name
            return


        # note that the tf coordinate system is right handed, with:
        #     X forward
        #     Y left
        #     Z up
        # ick.
        #
        # BTW, I'm assuming that the picture coordinate system is:
        #     X right
        #     Y down
        #     (0,0) at upper-left
        # which is also icky, but it's a familiar sort of icky.

        # after normalization, left & right give the Y value of those edges
        # of the bounding box, according to the tf convention
        # after normalization, top & bottom give the Z value of those edges
        # of the bounding box, according to the tf convention

        # to construct each plane, we build three points in the camera's
        # coordinate system, which form a triangle.  If you view the
        # triangle and see the points in a counter-clockwise direction,
        # then you are "in front of" the plane.  You would see them in
        # clockwise direction if you were in back of it.
        #
        # remember that the planes face inwards.

        # this is the object which will collect the 4 (or maybe 5)
        # planes we generate.
        poly = Convex_Space()
        poly.sensor = self.tf_name
        poly.algorithm = self.tf_name
        
        marker.points = []

        origin = Point(0,0,0)
        polygonStamped.polygon.points = []
	polygonStamped.polygon.points.append( self.ConvertToWorldPoint(origin) )
	# Gonna use the intrinsic camera matrix K to reverse project
	K = self.K_dict[self.tf_name]	
	for i in range(len(points)):
#                print "OLD POINT:   %s" % points[i]
		transformed = K.I*[[points[i].x], [points[i].y], [1]]
#                print "TRANSFORMED: %s" % transformed
		""" Camera thinks it's facing down the x-axis, while tf thinks it's
			facing down the z, so we put in (z, -x, y)
			y also has to be negated here, not sure why??? """
		polygonStamped.polygon.points.append( self.ConvertToWorldPoint( Point(transformed[2,0], -transformed[0,0], -transformed[1,0]) ))

	return polygonStamped





		# Old method
#		points[i].x = ( 1 - (2*points[i].x/self.xWid) * self.aspectXtoZ )
#		points[i].y = ( 1 - (2*points[i].y/self.yHei) * self.aspectYtoZ )
		
	""" This should add the points for each plane in the correct order,
		counter-clockwise if looking from within the pyramid """
        origin = Point(0,0,0)
	for point1,point2 in zip(points, points[1:]+[points[0]]):
	        poly.planes.append( self.GenPlane(origin, point2, point1) )
	 
        # finally, if front is positive, then we want to produce a bounding
        # plane there, facing away from the camera.  So, if we stand at the
        # origin, it should be a clockwise pattern.
        if front > 0:
            point1 = Point(front, 0,0)
            point2 = Point(front, 1,0)
            point2 = Point(front, 1,1)
            poly.planes.append( self.GenPlane(point1, point2, point3) )

	return poly
	
	#DEAD FOR NOW

        # we are at last ready to speak to the world!
        self.bb_publisher.publish(poly)

	""" This bit is for the purpose of testing the intersector
		It publishes a cube that should intersect with the
		bounding pyramid generated for the blue_block
	"""
	poly.sensor = "testing"
        poly.algorithm = "testing"
        poly.planes = []
        """
	# Front and Back planes
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(2,0,0),Point(2,1,0),Point(2,0,1)) )
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(1,0,0),Point(1,0,1),Point(1,1,0)) )
        # Right and Left planes
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,-2,0),Point(1,-2,0),Point(0,-2,1)) )
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,-1,0),Point(0,-1,1),Point(1,-1,0)) )
        """
        # Top and Bottom planes
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,0,1),Point(1,0,1),Point(0,1,1)) )
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,0,0),Point(0,1,0),Point(1,0,0)) )
        self.bb_publisher.publish(poly)
        
	        
        self.marker_pub.publish(marker)
Exemplo n.º 3
0
    def extractSpace(self):
        # this extracts a Convex_Space object from this intersection object.

        retval = Convex_Space()

        retval.planes = self.planes  # TODO: cull planes, someday

        retval.sensor    = "intersector"
        retval.algorithm = "intersector"

        # the aux_payload of the new Convex_Space is the union of all the
        # input payloads, plus the point list and bounding box we have
        # calculated.
        retval.aux_payload = ""
        for space in self.convex_spaces:
#            print "AUX PAYLOAD: " + space.aux_payload
            retval.aux_payload += space.aux_payload + "\n"
#        print
#        print retval.aux_payload
#        print

        # this little loop lists the points we have calculated...
        min_x = max_x = self.points[0].x
        min_y = max_y = self.points[0].y
        min_z = max_z = self.points[0].z

        pts_payload = ""

	global marker # added by Jeremy
        for pt in self.points:
            pts_payload += " (%f,%f,%f)" % (pt.x,pt.y,pt.z)
            marker.points.append(Point(pt.x,pt.y,pt.z)) # added by Jeremy

            if pt.x < min_x:
                min_x = pt.x
            if pt.x > max_x:
                max_x = pt.x

            if pt.y < min_y:
                min_y = pt.y
            if pt.y > max_y:
                max_y = pt.y

            if pt.z < min_z:
                min_z = pt.z
            if pt.z > max_z:
                max_z = pt.z

        bb_payload = "x=(%f,%f) y=(%f,%f) z=(%f,%f)" % (min_x,max_x, min_y,max_y, min_z,max_z)

        """ # added by Jeremy - show only bounding box
        marker.points.append(Point(min_x,min_y,min_z))
        marker.points.append(Point(min_x,min_y,max_z))
        marker.points.append(Point(min_x,max_y,max_z))
        marker.points.append(Point(max_x,max_y,max_z))
        marker.points.append(Point(max_x,max_y,min_z))
        marker.points.append(Point(max_x,min_y,min_z))
        marker.points.append(Point(max_x,min_y,max_z))
        marker.points.append(Point(min_x,max_y,min_z))
        """
        
        retval.aux_payload += "convex_set: %s\n" % pts_payload
        retval.aux_payload += "bounding_box: %s\n" % bb_payload

        # also, add a count of the input spaces as a quick estimate of how
        # interesting this object is.
        retval.aux_payload += "convex_space_count: %d" % len(self.convex_spaces)


        return retval
    def GenPlaneFromWorldPoints(self, point1, point2, point3):
        if (point1.x == point2.x and point1.y == point2.y and point1.z == point2.z) or (point1.x == point3.x and point1.y == point3.y and point1.z == point3.z) or (point2.x == point3.x and point2.y == point3.y and point2.z == point3.z):
            print "camera2boundingBox.pl:GenPlaneFromWorldPoints(): ERROR: 2 points were identical!!!  point1=%s point2=%s point3=%s" % (point1,point2,point3)
            return None


        AB = [(point2.x-point1.x),(point2.y-point1.y),(point2.z-point1.z)]
        AC = [(point3.x-point1.x),(point3.y-point1.y),(point3.z-point1.z)]

        normal = cross(AB,AC)

        # the a,b,c fields of the plane are the plane normal.  d is the
        # (negation of the) dot product of the normal times any point on the plane
        d = - dot(normal, [point1.x, point1.y, point1.z])

        print "GenPlaneFromWorldPoints: point1=(%f,%f,%f) point2=(%f,%f,%f) point3=(%f,%f,%f)" % (point1.x,point1.y,point1.z, point2.x,point2.y,point2.z, point3.x,point3.y,point3.z)
        print "GenPlaneFromWorldPoints: normal=(%f,%f,%f)" % (normal[0],normal[1],normal[2])
        print "GenPlaneFromWorldPoints: d=%f" % d
        print

        # BUGFIX: the planes generated were pointing the wrong direction.  Multiply
        # all values by -1.
#        return Plane(normal[0], normal[1], normal[2], d)
        return Plane(-normal[0], -normal[1], -normal[2], -d)







# DEAD CODE from here to the end of the class

        # this is the object which will collect the 4 (or maybe 5)
        # planes we generate.
        poly = Convex_Space()
        poly.sensor = self.tf_name
        poly.algorithm = self.tf_name
        
#        marker.points = []

	# Gonna use the intrinsic camera matrix K to reverse project
	K = self.K_dict[self.tf_name]	
	for i in range(len(points)):
		transformed = K.I*[[points[i].x], [points[i].y], [1]]
		""" Camera thinks it's facing down the x-axis, while tf thinks it's
			facing down the z, so we put in (z, -x, y)
			y also has to be negated here, not sure why??? """
		points[i] = Point(transformed[2,0], -transformed[0,0], -transformed[1,0])

		# Old method
#		points[i].x = ( 1 - (2*points[i].x/self.xWid) * self.aspectXtoZ )
#		points[i].y = ( 1 - (2*points[i].y/self.yHei) * self.aspectYtoZ )
		
	""" This should add the points for each plane in the correct order,
		counter-clockwise if looking from within the pyramid """
        origin = Point(0,0,0)
	for point1,point2 in zip(points, points[1:]+[points[0]]):
	        poly.planes.append( self.GenPlane(origin, point1, point2) )
	 
        # finally, if front is positive, then we want to produce a bounding
        # plane there, facing away from the camera.  So, if we stand at the
        # origin, it should be a clockwise pattern.
        if front > 0:
            point1 = Point(front, 0,0)
            point2 = Point(front, 1,0)
            point3 = Point(front, 1,1)
            poly.planes.append( self.GenPlane(point1, point2, point3) )


        # we are at last ready to speak to the world!
        self.bb_publisher.publish(poly)

	""" This bit is for the purpose of testing the intersector
		It publishes a cube that should intersect with the
		bounding pyramid generated for the blue_block
	"""
	poly.sensor = "testing"
        poly.algorithm = "testing"
        poly.planes = []
	# Front and Back planes
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(2,0,0),Point(2,1,0),Point(2,0,1)) )
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(1,0,0),Point(1,0,1),Point(1,1,0)) )
        # Right and Left planes
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,-2,0),Point(1,-2,0),Point(0,-2,1)) )
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,-1,0),Point(0,-1,1),Point(1,-1,0)) )
        # Top and Bottom planes
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,0,1),Point(1,0,1),Point(0,1,1)) )
        poly.planes.append( self.GenPlaneFromWorldPoints(Point(0,0,0),Point(0,1,0),Point(1,0,0)) )
        self.bb_publisher.publish(poly)
def init():
    output_name = "intersector_input"

    publisher = rospy.Publisher(output_name, Convex_Space)
    rospy.init_node('intersector')

    print "Sleep for 2 seconds to allow the 3d_intersector time to initialize..."
    rospy.Rate(.5).sleep()

    print "Sleep done..."



    print "Sending recorded shape information..."


# the following was recorded from "rostopic echo /intersector_input" during a run of one of our Gazebo tests
# ---
# planes: [
#     a: 0.0
#     b: 0.0
#     c: 1.0
#     d: -1.0,
#     a: 0.0
#     b: 0.0
#     c: -1.0
#     d: 0.0]
# sensor: horizontal_slicer
# algorithm: horizontal_slicer
# aux_payload: slicer:horizontal
# ---
# planes: [
#     a: -0.0507812052965
#     b: 0.0
#     c: -0.0324326232076
#     d: -0.0972978696227,
#     a: 3.45435147153e-08
#     b: 0.048828125
#     c: -0.0260353088379
#     d: -0.0781059265137,
#     a: 0.0507812090218
#     b: 0.0
#     c: 0.0299530699849
#     d: 0.0898592099547,
#     a: -3.12536556635e-08
#     b: -0.048828125
#     c: 0.0235557556152
#     d: 0.0706672668457]
# sensor: /overhead_cam
# algorithm: ian3
# aux_payload: ian3:blue
# ---
# planes: [
#     a: -5.19797671572e-09
#     b: -0.025390625
#     c: 0.0039176940918
#     d: 0.0117530822754,
#     a: -0.0253906045109
#     b: 0.0
#     c: -0.0159187652171
#     d: -0.0477562956512,
#     a: 6.05333960735e-09
#     b: 0.025390625
#     c: -0.00456237792969
#     d: -0.0136871337891,
#     a: 0.0253906045109
#     b: 0.0
#     c: 0.0152740813792
#     d: 0.0458222441375]
# sensor: /overhead_cam
# algorithm: ian3
# aux_payload: ian3:white
# ---
# planes: [
#     a: 6.38232577899e-09
#     b: -0.025390625
#     c: -0.00481033325195
#     d: -0.0144309997559,
#     a: -0.0253906026483
#     b: 0.0
#     c: -0.0162163116038
#     d: -0.0486489348114,
#     a: -5.52696244327e-09
#     b: 0.025390625
#     c: 0.00416564941406
#     d: 0.0124969482422,
#     a: 0.0253906045109
#     b: 0.0
#     c: 0.0155716277659
#     d: 0.0467148832977]
# sensor: /overhead_cam
# algorithm: ian3
# aux_payload: ian3:green
# ---
# planes: [
#     a: 3.46700481657e-08
#     b: -0.048828125
#     c: -0.0261306762695
#     d: -0.0783920288086,
#     a: -0.0507812052965
#     b: 0.0
#     c: -0.0324326232076
#     d: -0.0972978696227,
#     a: -3.13801891139e-08
#     b: 0.048828125
#     c: 0.0236511230469
#     d: 0.0709533691406,
#     a: 0.0507812090218
#     b: 0.0
#     c: 0.0299530699849
#     d: 0.0898592099547]
# sensor: /overhead_cam
# algorithm: ian3
# aux_payload: ian3:red
# ---


    space = Convex_Space()
    space.sensor      = "horizontal_slicer"
    space.algorithm   = "horizontal_slicer"
    space.aux_payload = "slicer:horizontal"

    space.planes = []

    plane = Plane()
    plane.a =  0
    plane.b =  0
    plane.c =  1
    plane.d = -1
    space.planes.append(plane)

    plane = Plane()
    plane.a =  0
    plane.b =  0
    plane.c = -1
    plane.d =  0
    space.planes.append(plane)

#    print "PUBLISHING: %s" % space
    publisher.publish(space)

    # ----

    space = Convex_Space()
    space.sensor      = "/overhead_cam"
    space.algorithm   = "ian3"
    space.aux_payload = "ian3:blue"

    space.planes = []

    plane = Plane()
    plane.a =  -0.0507812052965
    plane.b =   0.0
    plane.c =  -0.0324326232076
    plane.d =  -0.0972978696227
    space.planes.append(plane)

    plane = Plane()
    plane.a =  3.45435147153e-08
    plane.b =  0.048828125
    plane.c = -0.0260353088379
    plane.d = -0.0781059265137
    space.planes.append(plane)

    plane = Plane()
    plane.a = 0.0507812090218
    plane.b = 0.0
    plane.c = 0.0299530699849
    plane.d = 0.0898592099547
    space.planes.append(plane)

    plane = Plane()
    plane.a = -3.12536556635e-08
    plane.b = -0.048828125
    plane.c =  0.0235557556152
    plane.d =  0.0706672668457
    space.planes.append(plane)

#    print "PUBLISHING: %s" % space
    publisher.publish(space)

    # ----

    space = Convex_Space()
    space.sensor      = "/overhead_cam"
    space.algorithm   = "ian3"
    space.aux_payload = "ian3:white"

    space.planes = []

    plane = Plane()
    plane.a = -5.19797671572e-09
    plane.b = -0.025390625
    plane.c = 0.0039176940918
    plane.d = 0.0117530822754
    space.planes.append(plane)

    plane = Plane()
    plane.a = -0.0253906045109
    plane.b = 0.0
    plane.c = -0.0159187652171
    plane.d = -0.0477562956512
    space.planes.append(plane)

    plane = Plane()
    plane.a = 6.05333960735e-09
    plane.b = 0.025390625
    plane.c = -0.00456237792969
    plane.d = -0.0136871337891
    space.planes.append(plane)

    plane = Plane()
    plane.a = 0.0253906045109
    plane.b = 0.0
    plane.c = 0.0152740813792
    plane.d = 0.0458222441375
    space.planes.append(plane)

#    print "PUBLISHING: %s" % space
    publisher.publish(space)

    # ----

    space = Convex_Space()
    space.sensor      = "/overhead_cam"
    space.algorithm   = "ian3"
    space.aux_payload = "ian3:green"

    space.planes = []

    plane = Plane()
    plane.a = 6.38232577899e-09
    plane.b = -0.025390625
    plane.c = -0.00481033325195
    plane.d = -0.0144309997559
    space.planes.append(plane)

    plane = Plane()
    plane.a = -0.0253906026483
    plane.b = 0.0
    plane.c = -0.0162163116038
    plane.d = -0.0486489348114
    space.planes.append(plane)

    plane = Plane()
    plane.a = -5.52696244327e-09
    plane.b = 0.025390625
    plane.c = 0.00416564941406
    plane.d = 0.0124969482422
    space.planes.append(plane)

    plane = Plane()
    plane.a = 0.0253906045109
    plane.b = 0.0
    plane.c = 0.0155716277659
    plane.d = 0.0467148832977
    space.planes.append(plane)

#    print "PUBLISHING: %s" % space
    publisher.publish(space)

    # ----

    space = Convex_Space()
    space.sensor      = "/overhead_cam"
    space.algorithm   = "ian3"
    space.aux_payload = "ian3:red"

    space.planes = []

    plane = Plane()
    plane.a = 3.46700481657e-08
    plane.b = -0.048828125
    plane.c = -0.0261306762695
    plane.d = -0.0783920288086
    space.planes.append(plane)

    plane = Plane()
    plane.a = -0.0507812052965
    plane.b = 0.0
    plane.c = -0.0324326232076
    plane.d = -0.0972978696227
    space.planes.append(plane)

    plane = Plane()
    plane.a = -3.13801891139e-08
    plane.b = 0.048828125
    plane.c = 0.0236511230469
    plane.d = 0.0709533691406
    space.planes.append(plane)

    plane = Plane()
    plane.a = 0.0507812090218
    plane.b = 0.0
    plane.c = 0.0299530699849
    plane.d = 0.0898592099547
    space.planes.append(plane)

#    print "PUBLISHING: %s" % space
    publisher.publish(space)


    # END OF RECORDED PLANES

    return

    








    # this is a horizontal slicer
    space = Convex_Space()

    plane = Plane()
    plane.a = 0
    plane.b = 0
    plane.c = 1
    plane.d = -1

    space.planes.append(plane);

    plane = Plane()
    plane.a =  0
    plane.b =  0
    plane.c = -1
    plane.d =  0

    space.planes.append(plane);

    space.sensor      = "horizontal_slicer"
    space.algorithm   = "horizontal_slicer"
    space.aux_payload = "slicer:horizontal"

    publisher.publish(space)

    print "Just published a horizontal_slicer"
    rospy.Rate(1).sleep()

    

    # this generates something approximating the sort of pyramid which
    # camera2boundingBox would produce.
    #
    # Characteristic points:
    #     Camera:
    #         (0, 0, 3)
    #     Planes:
    #         (3, 3, 0)
    #         (3, 6, 0)
    #         (6, 3, 0)
    #         (6, 6, 0)

    space = Convex_Space()

    plane = Plane()
    plane.a = -1
    plane.b =  0
    plane.c = -1
    plane.d =  3

    space.planes.append(plane)
    
    plane = Plane()
    plane.a =  0
    plane.b = -1
    plane.c = -1
    plane.d =  3

    space.planes.append(plane)
    
    plane = Plane()
    plane.a =  0.5
    plane.b =  0
    plane.c =  1
    plane.d = -3

    space.planes.append(plane)
    
    plane = Plane()
    plane.a =  0
    plane.b =  0.5
    plane.c =  1
    plane.d = -3

    space.planes.append(plane)

    space.sensor      = "pseudo_pyramid"
    space.algorithm   = "pseudo_pyramid"
    space.aux_payload = ""

    publisher.publish(space)

    print "Just published a pseudo-pyramid"
    rospy.Rate(1).sleep()





    # test a few passes where we gradually reduce the box size.
    for radius in inclusive_range(10*1000, 5*1000, -1000):
        space = Convex_Space()

        plane = Plane()
        plane.a = 1
        plane.b = 0
        plane.c = 0
        plane.d = -radius
        print "plane: %s" % plane
        space.planes.append(plane)

        plane = Plane()
        plane.a = -1
        plane.b = 0
        plane.c = 0
        plane.d = -radius
        space.planes.append(plane)

        plane = Plane()
        plane.a = 0
        plane.b = 1
        plane.c = 0
        plane.d = -radius
        space.planes.append(plane)

        plane = Plane()
        plane.a = 0
        plane.b = -1
        plane.c = 0
        plane.d = -radius
        space.planes.append(plane)

        plane = Plane()
        plane.a = 0
        plane.b = 0
        plane.c = 1
        plane.d = -radius
        space.planes.append(plane)

        plane = Plane()
        plane.a = 0
        plane.b = 0
        plane.c = -1
        plane.d = -radius
        space.planes.append(plane)

        space.sensor      = "plane_slicer"
        space.algorithm   = "plane_slicer"
        space.aux_payload = "plane_slicer_radius=%d" % radius

        publisher.publish(space)

        print "Just published a plane-slicing space with radius=%d" % radius
        rospy.Rate(1).sleep()



    # remember that the initial box, defined in 3d_intersector, is +- 10*1000 in each dimension.
    #
    # With radius == 10*1000, we get 3 key points, which are the exact centers of 3 different
    # faces; the plane slices through those.  However, it works out that the plane also slices
    # through the 3 nearby corners of the original box.
    #
    # With radius == 20*1000, we get 3 key points, but these are now midpoints of edges, instead
    # of the center of faces.  Thus, each plane just slices off one corner of the cube.
    #
    # We'll test with 20k, then 10k, and see how our intersector handles it.
    for radius in inclusive_range(20*1000, 10*1000, -10*1000):
        space = Convex_Space()

        for a in range(-1, 1+1, 2):
            for b in range(-1, 1+1, 2):
                for c in range(-1, 1+1, 2):
                    plane = Plane()
                    plane.a = a
                    plane.b = b
                    plane.c = c
                    plane.d = -radius  # need negative d value, since we are adding it to the left-hand side of the inequality, and then checking if the value is small enough.

                    space.planes.append(plane)

        space.sensor     = "corner_slicer"
        space.algorithm  = "corner_slicer:radius=%d" % radius
        space.aux_payload = "corner_slicer_radius=%d" % radius

        publisher.publish(space)

        print "Just published a corner-slicing space with radius=%d" % radius
        rospy.Rate(1).sleep()