PointCloud2DLayer.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Google Inc.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
00005  * use this file except in compliance with the License. You may obtain a copy of
00006  * the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
00013  * License for the specific language governing permissions and limitations under
00014  * the License.
00015  */
00016 
00017 package org.ros.android.view.visualization.layer;
00018 
00019 import com.google.common.base.Preconditions;
00020 
00021 import org.jboss.netty.buffer.ChannelBuffer;
00022 import org.ros.android.view.visualization.Color;
00023 import org.ros.android.view.visualization.Vertices;
00024 import org.ros.android.view.visualization.VisualizationView;
00025 import org.ros.message.MessageListener;
00026 import org.ros.namespace.GraphName;
00027 import org.ros.node.ConnectedNode;
00028 import org.ros.node.topic.Subscriber;
00029 
00030 import java.nio.ByteOrder;
00031 import java.nio.FloatBuffer;
00032 
00033 import javax.microedition.khronos.opengles.GL10;
00034 
00035 import sensor_msgs.PointCloud2;
00036 import sensor_msgs.PointField;
00037 
00044 public class PointCloud2DLayer extends SubscriberLayer<PointCloud2> implements TfLayer {
00045 
00046   private static final Color FREE_SPACE_COLOR = Color.fromHexAndAlpha("377dfa", 0.1f);
00047   private static final Color OCCUPIED_SPACE_COLOR = Color.fromHexAndAlpha("377dfa", 0.3f);
00048   private static final float POINT_SIZE = 10.f;
00049 
00050   private final Object mutex;
00051 
00052   private GraphName frame;
00053   private FloatBuffer vertexFrontBuffer;
00054   private FloatBuffer vertexBackBuffer;
00055 
00056   public PointCloud2DLayer(String topicName) {
00057     this(GraphName.of(topicName));
00058   }
00059 
00060   public PointCloud2DLayer(GraphName topicName) {
00061     super(topicName, PointCloud2._TYPE);
00062     mutex = new Object();
00063   }
00064 
00065   @Override
00066   public void draw(VisualizationView view, GL10 gl) {
00067     if (vertexFrontBuffer != null) {
00068       synchronized (mutex) {
00069         Vertices.drawTriangleFan(gl, vertexFrontBuffer, FREE_SPACE_COLOR);
00070         // Drop the first point which is required for the triangle fan but is
00071         // not a range reading.
00072         FloatBuffer pointVertices = vertexFrontBuffer.duplicate();
00073         pointVertices.position(3);
00074         Vertices.drawPoints(gl, pointVertices, OCCUPIED_SPACE_COLOR, POINT_SIZE);
00075       }
00076     }
00077   }
00078 
00079   @Override
00080   public void onStart(VisualizationView view, ConnectedNode connectedNode) {
00081     super.onStart(view, connectedNode);
00082     Subscriber<PointCloud2> subscriber = getSubscriber();
00083     subscriber.addMessageListener(new MessageListener<PointCloud2>() {
00084       @Override
00085       public void onNewMessage(PointCloud2 pointCloud) {
00086         frame = GraphName.of(pointCloud.getHeader().getFrameId());
00087         updateVertexBuffer(pointCloud);
00088       }
00089     });
00090   }
00091 
00092   private void updateVertexBuffer(final PointCloud2 pointCloud) {
00093     // We expect an unordered, XYZ point cloud of 32-bit floats (i.e. the result of
00094     // pcl::toROSMsg()).
00095     // TODO(damonkohler): Make this more generic.
00096     Preconditions.checkArgument(pointCloud.getHeight() == 1);
00097     Preconditions.checkArgument(pointCloud.getIsDense());
00098     Preconditions.checkArgument(pointCloud.getFields().size() == 3);
00099     Preconditions.checkArgument(pointCloud.getFields().get(0).getDatatype() == PointField.FLOAT32);
00100     Preconditions.checkArgument(pointCloud.getFields().get(1).getDatatype() == PointField.FLOAT32);
00101     Preconditions.checkArgument(pointCloud.getFields().get(2).getDatatype() == PointField.FLOAT32);
00102     Preconditions.checkArgument(pointCloud.getPointStep() == 16);
00103     Preconditions.checkArgument(pointCloud.getData().order().equals(ByteOrder.LITTLE_ENDIAN));
00104     final int size = (pointCloud.getRowStep() / pointCloud.getPointStep() +
00105         1 /* triangle fan origin */) * 3 /* x, y, z */;
00106     if (vertexBackBuffer == null || vertexBackBuffer.capacity() < size) {
00107       vertexBackBuffer = Vertices.allocateBuffer(size);
00108     }
00109     vertexBackBuffer.clear();
00110     // We start with the origin of the triangle fan.
00111     vertexBackBuffer.put(0.f);
00112     vertexBackBuffer.put(0.f);
00113     vertexBackBuffer.put(0.f);
00114 
00115     final ChannelBuffer buffer = pointCloud.getData();
00116     while (buffer.readable()) {
00117       vertexBackBuffer.put(buffer.readFloat());
00118       vertexBackBuffer.put(buffer.readFloat());
00119       vertexBackBuffer.put(0.f);
00120       // Discard z data.
00121       buffer.readFloat();
00122       // Discard intensity.
00123       buffer.readFloat();
00124     }
00125     vertexBackBuffer.position(0);
00126     synchronized (mutex) {
00127       FloatBuffer tmp = vertexFrontBuffer;
00128       vertexFrontBuffer = vertexBackBuffer;
00129       vertexBackBuffer = tmp;
00130     }
00131   }
00132 
00133   @Override
00134   public GraphName getFrame() {
00135     return frame;
00136   }
00137 }


android_core
Author(s): Damon Kohler
autogenerated on Thu Jun 6 2019 21:20:07