ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I have successfully publish a PointCloud Map that almost the same/exactly the same compared with OccupancyGrid Map. The reason I am doing so is I would like to publish sensor reading in the form of PointCloud. With the Map in form of PointCloud, I may merge both sensor reading and map.

Below is the codes that I have used to accomplish this task.

#!/usr/bin/env python
import rospy
import struct
from std_msgs.msg import Header, ColorRGBA
from nav_msgs.msg import OccupancyGrid, MapMetaData
import sensor_msgs.point_cloud2 as pcl2
from sensor_msgs.msg import PointCloud2, PointField

def translate(value, leftMin, leftMax, rightMin, rightMax):
    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin

    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)

    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)

def point_cloud_xyzrgb(x, y, map_data, origin_x, origin_y, resolution):

    points = [] 
    lim_x = x
    lim_y = y
    for i in range(lim_x):
        for j in range(lim_y):
            x = translate(i,0,lim_x-1,origin_x,abs(origin_x)) #use float(i) or translate(i,0,lim_x-1,origin_x,abs(origin_x))
            y = translate(j,0,lim_x-1,origin_y,abs(origin_y)) #use float(j) or translate(j,0,lim_x-1,origin_y,abs(origin_y))
            z = 0
            pt = [x, y, z, 0]
            if map_data[i+ lim_x * j] == 0:
                r = 255
                g = 255
                b = 255
            elif map_data[i+ lim_x * j] == 100:
                r = 0
                g = 0
                b = 0
            else:
                r = 255
                g = 0
                b = 0

#           r = int(x * 255.0)
#           g = int(y * 255.0)
#           b = int(z * 255.0)
            a = 255
            rgb = struct.unpack('I', struct.pack('BBBB', b, g, r, a))[0]
            pt[3] = rgb
            points.append(pt)

    header = Header()
    header.stamp = rospy.Time.now()
    header.frame_id = 'map'
    fields = [PointField('x', 0, PointField.FLOAT32, 1),
          PointField('y', 4, PointField.FLOAT32, 1),
          PointField('z', 8, PointField.FLOAT32, 1),
          PointField('rgb', 12, PointField.UINT32, 1),
          # PointField('rgba', 12, PointField.UINT32, 1),
          ]
    point_cloud = pcl2.create_cloud(header, fields, points)
    point_cloud_map.publish(point_cloud)


def mapCB(data):
    map_header = data.header
    map_x = data.info.width
    map_y = data.info.height
    resolution = data.info.resolution
    origin_x = data.info.origin.position.x
    origin_y = data.info.origin.position.y
    map_data = data.data
    point_cloud_xyzrgb(map_x, map_y, map_data, origin_x, origin_y, resolution)

if __name__ == "__main__":

    rospy.init_node('PointCloud_Map_Generator')
    point_cloud_map = rospy.Publisher('point_cloud_map', PointCloud2, queue_size=10)
    raw_map = rospy.Subscriber("map", OccupancyGrid, mapCB)
    rate = rospy.Rate(10)

    try:
        while not rospy.is_shutdown():
            rate.sleep()

    except Exception as e:
        print(e)