Go to the documentation of this file.00001 package com.github.rosjava.android_apps.map_nav;
00002
00003 import android.content.Context;
00004 import android.os.Handler;
00005 import android.view.GestureDetector;
00006 import android.view.MotionEvent;
00007
00008 import geometry_msgs.PoseStamped;
00009 import geometry_msgs.PoseWithCovarianceStamped;
00010 import move_base_msgs.MoveBaseActionGoal;
00011
00012 import javax.microedition.khronos.opengles.GL10;
00013
00014 import org.ros.android.view.visualization.Camera;
00015 import org.ros.android.view.visualization.VisualizationView;
00016 import org.ros.android.view.visualization.layer.DefaultLayer;
00017 import org.ros.android.view.visualization.shape.PoseShape;
00018 import org.ros.android.view.visualization.shape.Shape;
00019 import org.ros.namespace.GraphName;
00020 import org.ros.namespace.NameResolver;
00021 import org.ros.node.ConnectedNode;
00022 import org.ros.node.Node;
00023 import org.ros.node.topic.Publisher;
00024 import org.ros.rosjava_geometry.FrameName;
00025 import org.ros.rosjava_geometry.FrameTransformTree;
00026 import org.ros.rosjava_geometry.Transform;
00027 import org.ros.rosjava_geometry.Vector3;
00028
00029 import com.google.common.base.Preconditions;
00030
00031 public class MapPosePublisherLayer extends DefaultLayer {
00032
00033 private static final String MAP_FRAME = "map";
00034 private static final String ROBOT_FRAME = "base_link";
00035 private static final String INITIAL_POSE_TOPIC = "initialpose";
00036 private static final String POSE_GOAL_TOPIC = "move_base_simple/goal";
00037 private static final String MOVE_BASE_GOAL_TOPIC = "move_base/goal";
00038
00039 private final Context context;
00040 private Shape shape;
00041 private Publisher<geometry_msgs.PoseWithCovarianceStamped> initialPosePublisher;
00042 private Publisher<geometry_msgs.PoseStamped> androidGoalPublisher;
00043 private Publisher<MoveBaseActionGoal> goalPublisher;
00044 private boolean visible;
00045 private NameResolver nameResolver;
00046 private GestureDetector gestureDetector;
00047 private Transform pose;
00048 private Transform fixedPose;
00049 private Camera camera;
00050 private ConnectedNode connectedNode;
00051 private int mode;
00052 private static final int POSE_MODE = 0;
00053 private static final int GOAL_MODE = 1;
00054
00055 public MapPosePublisherLayer(NameResolver newNameResolver, Context context) {
00056 this.nameResolver = newNameResolver;
00057 this.context = context;
00058 visible = false;
00059 }
00060
00061 public void setPoseMode() {
00062 mode = POSE_MODE;
00063 }
00064
00065 public void setGoalMode() {
00066 mode = GOAL_MODE;
00067 }
00068
00069 @Override
00070 public void draw(GL10 gl) {
00071 if (visible) {
00072 Preconditions.checkNotNull(pose);
00073 shape.draw(gl);
00074 }
00075 }
00076
00077 private double angle(double x1, double y1, double x2, double y2) {
00078 double deltaX = x1 - x2;
00079 double deltaY = y1 - y2;
00080 return Math.atan2(deltaY, deltaX);
00081 }
00082
00083 @Override
00084 public boolean onTouchEvent(VisualizationView view, MotionEvent event) {
00085 if (visible) {
00086 Preconditions.checkNotNull(pose);
00087
00088 Vector3 poseVector;
00089 Vector3 pointerVector;
00090
00091 if (event.getAction() == MotionEvent.ACTION_MOVE) {
00092 poseVector = pose.apply(Vector3.zero());
00093 pointerVector = camera.toMetricCoordinates((int) event.getX(),
00094 (int) event.getY());
00095
00096 double angle = angle(pointerVector.getX(),
00097 pointerVector.getY(), poseVector.getX(),
00098 poseVector.getY());
00099 pose = Transform.translation(poseVector).multiply(
00100 Transform.zRotation(angle));
00101
00102 shape.setTransform(pose);
00103 return true;
00104 }
00105 if (event.getAction() == MotionEvent.ACTION_UP) {
00106
00107 PoseStamped poseStamped;
00108 switch (mode) {
00109 case POSE_MODE:
00110 camera.setFrame(MAP_FRAME);
00111 poseVector = fixedPose.apply(Vector3.zero());
00112 pointerVector = camera.toMetricCoordinates(
00113 (int) event.getX(), (int) event.getY());
00114 double angle2 = angle(pointerVector.getX(),
00115 pointerVector.getY(), poseVector.getX(),
00116 poseVector.getY());
00117 fixedPose = Transform.translation(poseVector).multiply(
00118 Transform.zRotation(angle2));
00119 camera.setFrame(ROBOT_FRAME);
00120 poseStamped = fixedPose.toPoseStampedMessage(
00121 FrameName.of(ROBOT_FRAME),
00122 connectedNode.getCurrentTime(),
00123 androidGoalPublisher.newMessage());
00124
00125 PoseWithCovarianceStamped initialPose = initialPosePublisher.newMessage();
00126 initialPose.getHeader().setFrameId(MAP_FRAME);
00127 initialPose.getPose().setPose(poseStamped.getPose());
00128 double[] covariance = initialPose.getPose().getCovariance();
00129 covariance[6 * 0 + 0] = 0.5 * 0.5;
00130 covariance[6 * 1 + 1] = 0.5 * 0.5;
00131 covariance[6 * 5 + 5] = (float) (Math.PI / 12.0 * Math.PI / 12.0);
00132
00133 initialPosePublisher.publish(initialPose);
00134 break;
00135 case GOAL_MODE:
00136 poseStamped = pose.toPoseStampedMessage(
00137 FrameName.of(ROBOT_FRAME),
00138 connectedNode.getCurrentTime(),
00139 androidGoalPublisher.newMessage());
00140 androidGoalPublisher.publish(poseStamped);
00141
00142 move_base_msgs.MoveBaseActionGoal message = goalPublisher.newMessage();
00143 message.setHeader(poseStamped.getHeader());
00144 message.getGoalId().setStamp(connectedNode.getCurrentTime());
00145 message.getGoalId().setId("move_base/move_base_client_android"
00146 + connectedNode.getCurrentTime().toString());
00147 message.getGoal().setTargetPose(poseStamped);
00148 goalPublisher.publish(message);
00149 break;
00150 }
00151 visible = false;
00152 return true;
00153 }
00154 }
00155 gestureDetector.onTouchEvent(event);
00156 return false;
00157 }
00158
00159 @Override
00160 public void onStart(ConnectedNode connectedNode, Handler handler,
00161 FrameTransformTree frameTransformTree, final Camera camera) {
00162 this.connectedNode = connectedNode;
00163 this.camera = camera;
00164 shape = new PoseShape(camera);
00165 mode = POSE_MODE;
00166 initialPosePublisher = connectedNode.newPublisher(
00167 nameResolver.resolve(INITIAL_POSE_TOPIC).toString(),
00168 "geometry_msgs/PoseWithCovarianceStamped");
00169 androidGoalPublisher = connectedNode.newPublisher(
00170 nameResolver.resolve(POSE_GOAL_TOPIC).toString(),
00171 "geometry_msgs/PoseStamped");
00172 goalPublisher = connectedNode.newPublisher(
00173 nameResolver.resolve(MOVE_BASE_GOAL_TOPIC).toString(),
00174 "move_base_msgs/MoveBaseActionGoal");
00175 handler.post(new Runnable() {
00176 @Override
00177 public void run() {
00178 gestureDetector = new GestureDetector(context,
00179 new GestureDetector.SimpleOnGestureListener() {
00180 @Override
00181 public void onLongPress(MotionEvent e) {
00182 pose = Transform.translation(camera.toMetricCoordinates(
00183 (int) e.getX(), (int) e.getY()));
00184 shape.setTransform(pose);
00185 camera.setFrame(MAP_FRAME);
00186 fixedPose = Transform.translation(camera.toMetricCoordinates(
00187 (int) e.getX(), (int) e.getY()));
00188 camera.setFrame(ROBOT_FRAME);
00189 visible = true;
00190 }
00191 });
00192 }
00193 });
00194 }
00195
00196 @Override
00197 public void onShutdown(VisualizationView view, Node node) {
00198 initialPosePublisher.shutdown();
00199 androidGoalPublisher.shutdown();
00200 goalPublisher.shutdown();
00201 }
00202 }