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;
00018
00019 import com.google.common.base.Preconditions;
00020
00021 import org.ros.math.RosMath;
00022 import org.ros.namespace.GraphName;
00023 import org.ros.rosjava_geometry.FrameTransform;
00024 import org.ros.rosjava_geometry.FrameTransformTree;
00025 import org.ros.rosjava_geometry.Transform;
00026 import org.ros.rosjava_geometry.Vector3;
00027
00028 import javax.microedition.khronos.opengles.GL10;
00029
00034 public class XYOrthographicCamera {
00035
00041 private static final double PIXELS_PER_METER = 100.0;
00042
00048 private static final Transform ROS_TO_SCREEN_TRANSFORM = Transform.zRotation(Math.PI / 2).scale(
00049 PIXELS_PER_METER);
00050
00054 private static final float MINIMUM_ZOOM_FACTOR = 0.1f;
00055
00059 private static final float MAXIMUM_ZOOM_FACTOR = 5.f;
00060
00061 private final FrameTransformTree frameTransformTree;
00062 private final Object mutex;
00063
00064 private Viewport viewport;
00065
00070 private Transform cameraToRosTransform;
00071
00078 private GraphName frame;
00079
00080 public XYOrthographicCamera(FrameTransformTree frameTransformTree) {
00081 this.frameTransformTree = frameTransformTree;
00082 mutex = new Object();
00083 resetTransform();
00084 }
00085
00086 private void resetTransform() {
00087 cameraToRosTransform = Transform.identity();
00088 }
00089
00090 public void apply(GL10 gl) {
00091 synchronized (mutex) {
00092 OpenGlTransform.apply(gl, ROS_TO_SCREEN_TRANSFORM);
00093 OpenGlTransform.apply(gl, cameraToRosTransform);
00094 }
00095 }
00096
00097 public boolean applyFrameTransform(GL10 gl, GraphName frame) {
00098 Preconditions.checkNotNull(frame);
00099 if (this.frame != null) {
00100 FrameTransform frameTransform = frameTransformTree.transform(frame, this.frame);
00101 if (frameTransform != null) {
00102 OpenGlTransform.apply(gl, frameTransform.getTransform());
00103 return true;
00104 }
00105 }
00106 return false;
00107 }
00108
00115 public void translate(double deltaX, double deltaY) {
00116 synchronized (mutex) {
00117 cameraToRosTransform =
00118 ROS_TO_SCREEN_TRANSFORM.invert().multiply(Transform.translation(deltaX, deltaY, 0))
00119 .multiply(getCameraToScreenTransform());
00120 }
00121 }
00122
00123 private Transform getCameraToScreenTransform() {
00124 return ROS_TO_SCREEN_TRANSFORM.multiply(cameraToRosTransform);
00125 }
00126
00127 public Transform getScreenTransform(GraphName targetFrame) {
00128 FrameTransform frameTransform = frameTransformTree.transform(frame, targetFrame);
00129 return frameTransform.getTransform().multiply(getCameraToScreenTransform().invert());
00130 }
00131
00139 public void rotate(double focusX, double focusY, double deltaAngle) {
00140 synchronized (mutex) {
00141 Transform focus = Transform.translation(toCameraFrame((int) focusX, (int) focusY));
00142 cameraToRosTransform =
00143 cameraToRosTransform.multiply(focus).multiply(Transform.zRotation(deltaAngle))
00144 .multiply(focus.invert());
00145 }
00146 }
00147
00155 public void zoom(double focusX, double focusY, double factor) {
00156 synchronized (mutex) {
00157 Transform focus = Transform.translation(toCameraFrame((int) focusX, (int) focusY));
00158 double scale = cameraToRosTransform.getScale();
00159 double zoom = RosMath.clamp(scale * factor, MINIMUM_ZOOM_FACTOR, MAXIMUM_ZOOM_FACTOR) / scale;
00160 cameraToRosTransform =
00161 cameraToRosTransform.multiply(focus).scale(zoom).multiply(focus.invert());
00162 }
00163 }
00164
00168 public double getZoom() {
00169 return cameraToRosTransform.getScale() * PIXELS_PER_METER;
00170 }
00171
00176 public Vector3 toCameraFrame(int pixelX, int pixelY) {
00177 final double centeredX = pixelX - viewport.getWidth() / 2.0d;
00178 final double centeredY = viewport.getHeight() / 2.0d - pixelY;
00179 return getCameraToScreenTransform().invert().apply(new Vector3(centeredX, centeredY, 0));
00180 }
00181
00188 public Transform toFrame(final int pixelX, final int pixelY, final GraphName frame) {
00189 final Transform translation = Transform.translation(toCameraFrame(pixelX, pixelY));
00190 final FrameTransform cameraToFrame =
00191 frameTransformTree.transform(this.frame, frame);
00192 return cameraToFrame.getTransform().multiply(translation);
00193 }
00194
00195 public GraphName getFrame() {
00196 return frame;
00197 }
00198
00206 public void setFrame(GraphName frame) {
00207 Preconditions.checkNotNull(frame);
00208 synchronized (mutex) {
00209 if (this.frame != null && this.frame != frame) {
00210 FrameTransform frameTransform = frameTransformTree.transform(frame, this.frame);
00211 if (frameTransform != null) {
00212
00213
00214 cameraToRosTransform = cameraToRosTransform.multiply(frameTransform.getTransform());
00215 }
00216 }
00217 this.frame = frame;
00218 }
00219 }
00220
00224 public void setFrame(String frame) {
00225 setFrame(GraphName.of(frame));
00226 }
00227
00234 public void jumpToFrame(GraphName frame) {
00235 synchronized (mutex) {
00236 this.frame = frame;
00237 final double scale = cameraToRosTransform.getScale();
00238 resetTransform();
00239 cameraToRosTransform = cameraToRosTransform.scale(scale / cameraToRosTransform.getScale());
00240 }
00241 }
00242
00246 public void jumpToFrame(String frame) {
00247 jumpToFrame(GraphName.of(frame));
00248 }
00249
00250 public void setViewport(Viewport viewport) {
00251 Preconditions.checkNotNull(viewport);
00252 this.viewport = viewport;
00253 }
00254
00255 public Viewport getViewport() {
00256 Preconditions.checkNotNull(viewport);
00257 return viewport;
00258 }
00259
00260 public Transform getCameraToRosTransform() {
00261
00262 return cameraToRosTransform;
00263 }
00264 }