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