Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 package org.ros.android.compressed_map_transport;
00018
00019 import org.jboss.netty.buffer.ChannelBuffer;
00020 import org.jboss.netty.buffer.ChannelBufferOutputStream;
00021 import org.ros.exception.RosRuntimeException;
00022 import org.ros.internal.message.MessageBuffers;
00023 import org.ros.message.MessageListener;
00024 import org.ros.namespace.GraphName;
00025 import org.ros.node.AbstractNodeMain;
00026 import org.ros.node.ConnectedNode;
00027 import org.ros.node.topic.Publisher;
00028 import org.ros.node.topic.Subscriber;
00029
00030 import java.awt.Image;
00031 import java.awt.Transparency;
00032 import java.awt.color.ColorSpace;
00033 import java.awt.image.BufferedImage;
00034 import java.awt.image.ColorModel;
00035 import java.awt.image.ComponentColorModel;
00036 import java.awt.image.DataBuffer;
00037 import java.awt.image.DataBufferByte;
00038 import java.awt.image.Raster;
00039 import java.awt.image.SampleModel;
00040 import java.awt.image.WritableRaster;
00041 import java.io.IOException;
00042
00043 import javax.imageio.ImageIO;
00044
00050 public class CompressedMapTransport extends AbstractNodeMain {
00051
00052 private static final int MAXIMUM_WIDTH = 1024;
00053 private static final int MAXIMUM_HEIGHT = 1024;
00054 private static final String IMAGE_FORMAT = "png";
00055 private static final GraphName TOPIC_IN = GraphName.of("map");
00056 private static final GraphName TOPIC_OUT = TOPIC_IN.join(IMAGE_FORMAT);
00057
00058 private Publisher<nav_msgs.OccupancyGrid> publisher;
00059 private Subscriber<nav_msgs.OccupancyGrid> subscriber;
00060
00061 @Override
00062 public GraphName getDefaultNodeName() {
00063 return GraphName.of("map_transport");
00064 }
00065
00066 @Override
00067 public void onStart(ConnectedNode connectedNode) {
00068 publisher = connectedNode.newPublisher(TOPIC_OUT, nav_msgs.OccupancyGrid._TYPE);
00069 publisher.setLatchMode(true);
00070 subscriber = connectedNode.newSubscriber(TOPIC_IN, nav_msgs.OccupancyGrid._TYPE);
00071 subscriber.addMessageListener(new MessageListener<nav_msgs.OccupancyGrid>() {
00072 @Override
00073 public void onNewMessage(nav_msgs.OccupancyGrid message) {
00074 if (message.getInfo().getWidth() > 0 && message.getInfo().getHeight() > 0) {
00075 publisher.publish(scaleAndCompressOccupancyGrid(message));
00076 }
00077 }
00078 });
00079 }
00080
00081 private nav_msgs.OccupancyGrid scaleAndCompressOccupancyGrid(nav_msgs.OccupancyGrid message) {
00082 BufferedImage bufferedImage = newGrayscaleBufferedImage(message);
00083 BufferedImage scaledBufferedImage = scaleBufferedImage(bufferedImage);
00084 ChannelBuffer buffer = MessageBuffers.dynamicBuffer();
00085 ChannelBufferOutputStream outputStream = new ChannelBufferOutputStream(buffer);
00086 try {
00087 ImageIO.write(scaledBufferedImage, IMAGE_FORMAT, outputStream);
00088 } catch (IOException e) {
00089 throw new RosRuntimeException(e);
00090 }
00091 nav_msgs.OccupancyGrid compressedMessage = publisher.newMessage();
00092 compressedMessage.getHeader().setFrameId(message.getHeader().getFrameId());
00093 compressedMessage.getHeader().setStamp(message.getHeader().getStamp());
00094 compressedMessage.getInfo().setMapLoadTime(message.getInfo().getMapLoadTime());
00095 compressedMessage.getInfo().setOrigin(message.getInfo().getOrigin());
00096 compressedMessage.getInfo().setWidth(scaledBufferedImage.getWidth());
00097 compressedMessage.getInfo().setHeight(scaledBufferedImage.getHeight());
00098 float resolution =
00099 message.getInfo().getResolution() * message.getInfo().getHeight()
00100 / scaledBufferedImage.getHeight();
00101 compressedMessage.getInfo().setResolution(resolution);
00102 compressedMessage.setData(buffer);
00103 return compressedMessage;
00104 }
00105
00106 private BufferedImage newGrayscaleBufferedImage(nav_msgs.OccupancyGrid message) {
00107 int width = message.getInfo().getWidth();
00108 int height = message.getInfo().getHeight();
00109 ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
00110 ColorModel colorModel =
00111 new ComponentColorModel(colorSpace, new int[] { 8 }, false, false, Transparency.OPAQUE,
00112 DataBuffer.TYPE_BYTE);
00113 SampleModel sampleModel = colorModel.createCompatibleSampleModel(width, height);
00114
00115
00116
00117 byte[] data = new byte[message.getData().readableBytes()];
00118 message.getData().readBytes(data);
00119 DataBuffer dataBuffer = new DataBufferByte(data, data.length, 0);
00120 WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);
00121 BufferedImage bufferedImage = new BufferedImage(colorModel, raster, false, null);
00122 return bufferedImage;
00123 }
00124
00125 private BufferedImage scaleBufferedImage(BufferedImage bufferedImage) {
00126 int height = bufferedImage.getHeight();
00127 int width = bufferedImage.getWidth();
00128 BufferedImage scaledBufferedImage = bufferedImage;
00129 if (height > MAXIMUM_HEIGHT || width > MAXIMUM_WIDTH) {
00130
00131
00132 int scaledHeight = -1;
00133 int scaledWidth = -1;
00134 if (height > width) {
00135 scaledHeight = MAXIMUM_HEIGHT;
00136 } else {
00137 scaledWidth = MAXIMUM_WIDTH;
00138 }
00139 Image image = bufferedImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
00140 scaledBufferedImage =
00141 new BufferedImage(image.getWidth(null), image.getHeight(null),
00142 BufferedImage.TYPE_BYTE_GRAY);
00143 scaledBufferedImage.getGraphics().drawImage(image, 0, 0, null);
00144 }
00145 return scaledBufferedImage;
00146 }
00147 }