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.view.visualization.layer;
00018
00019 import com.google.common.base.Preconditions;
00020 import com.google.common.collect.Lists;
00021
00022 import org.jboss.netty.buffer.ChannelBuffer;
00023 import org.ros.android.view.visualization.TextureBitmap;
00024 import org.ros.android.view.visualization.VisualizationView;
00025 import org.ros.internal.message.MessageBuffers;
00026 import org.ros.message.MessageListener;
00027 import org.ros.namespace.GraphName;
00028 import org.ros.node.ConnectedNode;
00029 import org.ros.rosjava_geometry.Quaternion;
00030 import org.ros.rosjava_geometry.Transform;
00031 import org.ros.rosjava_geometry.Vector3;
00032
00033 import java.util.List;
00034
00035 import javax.microedition.khronos.opengles.GL10;
00036
00040 public class OccupancyGridLayer extends SubscriberLayer<nav_msgs.OccupancyGrid> implements TfLayer {
00041
00045 private static final int COLOR_OCCUPIED = 0xff111111;
00046
00050 private static final int COLOR_FREE = 0xffffffff;
00051
00055 private static final int COLOR_UNKNOWN = 0xffdddddd;
00056
00061 private class Tile {
00062
00063 private final ChannelBuffer pixelBuffer = MessageBuffers.dynamicBuffer();
00064 private final TextureBitmap textureBitmap = new TextureBitmap();
00065
00069 private final float resolution;
00070
00074 private Transform origin;
00075
00079 private int stride;
00080
00084 private boolean ready;
00085
00086 public Tile(float resolution) {
00087 this.resolution = resolution;
00088 ready = false;
00089 }
00090
00091 public void draw(VisualizationView view, GL10 gl) {
00092 if (ready) {
00093 textureBitmap.draw(view, gl);
00094 }
00095 }
00096
00097 public void clearHandle() {
00098 textureBitmap.clearHandle();
00099 }
00100
00101 public void writeInt(int value) {
00102 pixelBuffer.writeInt(value);
00103 }
00104
00105 public void update() {
00106 Preconditions.checkNotNull(origin);
00107 Preconditions.checkNotNull(stride);
00108 textureBitmap.updateFromPixelBuffer(pixelBuffer, stride, resolution, origin, COLOR_UNKNOWN);
00109 pixelBuffer.clear();
00110 ready = true;
00111 }
00112
00113 public void setOrigin(Transform origin) {
00114 this.origin = origin;
00115 }
00116
00117 public void setStride(int stride) {
00118 this.stride = stride;
00119 }
00120 }
00121
00122 private final List<Tile> tiles;
00123
00124 private boolean ready;
00125 private GraphName frame;
00126 private GL10 previousGl;
00127
00128 public OccupancyGridLayer(String topic) {
00129 this(GraphName.of(topic));
00130 }
00131
00132 public OccupancyGridLayer(GraphName topic) {
00133 super(topic, nav_msgs.OccupancyGrid._TYPE);
00134 tiles = Lists.newCopyOnWriteArrayList();
00135 ready = false;
00136 }
00137
00138 @Override
00139 public void draw(VisualizationView view, GL10 gl) {
00140 if (previousGl != gl) {
00141 for (Tile tile : tiles) {
00142 tile.clearHandle();
00143 }
00144 previousGl = gl;
00145 }
00146 if (ready) {
00147 for (Tile tile : tiles) {
00148 tile.draw(view, gl);
00149 }
00150 }
00151 }
00152
00153 @Override
00154 public GraphName getFrame() {
00155 return frame;
00156 }
00157
00158 @Override
00159 public void onStart(VisualizationView view, ConnectedNode connectedNode) {
00160 super.onStart(view, connectedNode);
00161 previousGl = null;
00162 getSubscriber().addMessageListener(new MessageListener<nav_msgs.OccupancyGrid>() {
00163 @Override
00164 public void onNewMessage(nav_msgs.OccupancyGrid message) {
00165 update(message);
00166 }
00167 });
00168 }
00169
00170 private void update(nav_msgs.OccupancyGrid message) {
00171 final float resolution = message.getInfo().getResolution();
00172 final int width = message.getInfo().getWidth();
00173 final int height = message.getInfo().getHeight();
00174 final int numTilesWide = (int) Math.ceil(width / (float) TextureBitmap.STRIDE);
00175 final int numTilesHigh = (int) Math.ceil(height / (float) TextureBitmap.STRIDE);
00176 final int numTiles = numTilesWide * numTilesHigh;
00177 final Transform origin = Transform.fromPoseMessage(message.getInfo().getOrigin());
00178
00179 while (tiles.size() < numTiles) {
00180 tiles.add(new Tile(resolution));
00181 }
00182
00183 for (int y = 0; y < numTilesHigh; ++y) {
00184 for (int x = 0; x < numTilesWide; ++x) {
00185 final int tileIndex = y * numTilesWide + x;
00186 tiles.get(tileIndex).setOrigin(origin.multiply(new Transform(new Vector3(x *
00187 resolution * TextureBitmap.STRIDE,
00188 y * resolution * TextureBitmap.HEIGHT, 0.), Quaternion.identity())));
00189 if (x < numTilesWide - 1) {
00190 tiles.get(tileIndex).setStride(TextureBitmap.STRIDE);
00191 } else {
00192 tiles.get(tileIndex).setStride(width % TextureBitmap.STRIDE);
00193 }
00194 }
00195 }
00196
00197 int x = 0;
00198 int y = 0;
00199 final ChannelBuffer buffer = message.getData();
00200 while (buffer.readable()) {
00201 Preconditions.checkState(y < height);
00202 final int tileIndex = (y / TextureBitmap.STRIDE) * numTilesWide + x / TextureBitmap.STRIDE;
00203 final byte pixel = buffer.readByte();
00204 if (pixel == -1) {
00205 tiles.get(tileIndex).writeInt(COLOR_UNKNOWN);
00206 } else {
00207 if (pixel < 50) {
00208 tiles.get(tileIndex).writeInt(COLOR_FREE);
00209 } else {
00210 tiles.get(tileIndex).writeInt(COLOR_OCCUPIED);
00211 }
00212 }
00213
00214 ++x;
00215 if (x == width) {
00216 x = 0;
00217 ++y;
00218 }
00219 }
00220
00221 for (Tile tile : tiles) {
00222 tile.update();
00223 }
00224
00225 frame = GraphName.of(message.getHeader().getFrameId());
00226 ready = true;
00227 }
00228 }