TurtlebotDashboard.java
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright (c) 2011, Willow Garage, Inc.
00005  * All rights reserved.
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above
00013  *    copyright notice, this list of conditions and the following
00014  *    disclaimer in the documentation and/or other materials provided
00015  *    with the distribution.
00016  *  * Neither the name of Willow Garage, Inc. nor the names of its
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031  * POSSIBILITY OF SUCH DAMAGE.
00032  */
00033 
00034 
00035 package com.github.turtlebot.turtlebot_android.turtlebot_core;
00036 
00037 import java.util.HashMap;
00038 import java.util.List;
00039 
00040 import com.github.rosjava.android_apps.application_management.Dashboard.DashboardInterface;
00041 import com.github.rosjava.android_extras.gingerbread.view.BatteryLevelView;
00042 import org.ros.exception.RemoteException;
00043 import org.ros.exception.RosException;
00044 import org.ros.message.MessageListener;
00045 import org.ros.namespace.GraphName;
00046 import org.ros.namespace.NameResolver;
00047 import org.ros.node.ConnectedNode;
00048 import org.ros.node.Node;
00049 import org.ros.node.service.ServiceClient;
00050 import org.ros.node.service.ServiceResponseListener;
00051 import org.ros.node.topic.Subscriber;
00052 
00053 import create_node.SetDigitalOutputsRequest;
00054 import create_node.SetDigitalOutputsResponse;
00055 import create_node.SetTurtlebotModeRequest;
00056 import create_node.SetTurtlebotModeResponse;
00057 import create_node.TurtlebotSensorState;
00058 
00059 import diagnostic_msgs.DiagnosticArray;
00060 import diagnostic_msgs.DiagnosticStatus;
00061 import diagnostic_msgs.KeyValue;
00062 
00063 import android.content.Context;
00064 import android.graphics.Color;
00065 import android.util.AttributeSet;
00066 import android.util.Log;
00067 import android.view.LayoutInflater;
00068 import android.view.View;
00069 import android.widget.ImageButton;
00070 import android.widget.LinearLayout;
00071 import android.widget.ProgressBar;
00072 import android.widget.Toast;
00073 
00074 
00075 public class TurtlebotDashboard extends LinearLayout implements DashboardInterface {
00076     private ImageButton modeButton;
00077     private ProgressBar modeWaitingSpinner;
00078     private BatteryLevelView robotBattery;
00079     private BatteryLevelView laptopBattery;
00080     private ConnectedNode connectedNode;
00081     private Subscriber<diagnostic_msgs.DiagnosticArray> diagnosticSubscriber;
00082     private boolean powerOn = false;
00083     private int numModeResponses;
00084     private int numModeErrors;
00085     
00086     public TurtlebotDashboard(Context context) {
00087             super(context);
00088             inflateSelf(context);
00089     }
00090     public TurtlebotDashboard(Context context, AttributeSet attrs) {
00091             super(context, attrs);
00092             inflateSelf(context);
00093     }
00094     private void inflateSelf(Context context) {
00095             LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
00096             inflater.inflate(R.layout.turtlebot_dashboard, this);
00097             modeButton = (ImageButton) findViewById(R.id.mode_button);
00098             modeButton.setOnClickListener(new OnClickListener() {
00099                     @Override
00100                     public void onClick(View v) {
00101                             onModeButtonClicked();
00102                     }
00103             });
00104             modeWaitingSpinner = (ProgressBar) findViewById(R.id.mode_waiting_spinner);
00105             modeWaitingSpinner.setIndeterminate(true);
00106             modeWaitingSpinner.setVisibility(View.GONE);
00107             robotBattery = (BatteryLevelView) findViewById(R.id.robot_battery);
00108             laptopBattery = (BatteryLevelView) findViewById(R.id.laptop_battery);
00109     }
00120     private void handleDiagnosticArray(DiagnosticArray msg) {
00121             String mode = null;
00122             for(DiagnosticStatus status : msg.getStatus()) {
00123                     if(status.getName().equals("/Power System/Battery")) {
00124                             populateBatteryFromStatus(robotBattery, status);
00125                     }
00126                     if(status.getName().equals("/Power System/Laptop Battery")) {
00127                             populateBatteryFromStatus(laptopBattery, status);
00128                     }
00129                     if(status.getName().equals("/Mode/Operating Mode")) {
00130                             mode = status.getMessage();
00131                     }
00132             }
00133             showMode(mode);
00134     }
00135     
00136    
00137     private void onModeButtonClicked() {
00138             powerOn = !powerOn;
00139             SetTurtlebotModeRequest modeRequest = connectedNode.getTopicMessageFactory().newFromType(SetTurtlebotModeRequest._TYPE);
00140             SetDigitalOutputsRequest setDigOutRequest = connectedNode.getTopicMessageFactory().newFromType(SetDigitalOutputsRequest._TYPE);
00141             setDigOutRequest.setDigitalOut1((byte) 0);
00142             setDigOutRequest.setDigitalOut2((byte) 0);
00143             if(powerOn) {
00144                     modeRequest.setMode(TurtlebotSensorState.OI_MODE_FULL);
00145                     setDigOutRequest.setDigitalOut0((byte) 1); // main breaker on
00146             } else {
00147                     modeRequest.setMode(TurtlebotSensorState.OI_MODE_PASSIVE);
00148                     setDigOutRequest.setDigitalOut0((byte) 0); // main breaker off
00149             }
00150             setModeWaiting(true);
00151             numModeResponses = 0;
00152             numModeErrors = 0;
00153             // TODO: can't I save the modeServiceClient? Causes trouble.
00154             try {
00155                     ServiceClient<SetTurtlebotModeRequest, SetTurtlebotModeResponse> modeServiceClient = connectedNode.newServiceClient("turtlebot_node/set_operation_mode", "turtlebot_node/SetTurtlebotMode");
00156                     modeServiceClient.call(modeRequest, new ServiceResponseListener<SetTurtlebotModeResponse>() {
00157                             @Override
00158                             public void onSuccess(SetTurtlebotModeResponse message) {
00159                                     numModeResponses++;
00160                                     updateModeWaiting();
00161                             }
00162                             @Override
00163                             public void onFailure(RemoteException e) {
00164                                     numModeResponses++;
00165                                     numModeErrors++;
00166                                     updateModeWaiting();
00167                             }
00168                     });
00169             } catch(Exception ex) {
00170                     Toast.makeText(getContext(), "Exception in service call for set_operation_mode: " + ex.getMessage(), Toast.LENGTH_LONG).show();
00171                     Log.i("TurtlebotDashboard", "making toast.");
00172             }
00173             try {
00174                     ServiceClient<SetDigitalOutputsRequest, SetDigitalOutputsResponse> setDigOutServiceClient = connectedNode.newServiceClient("turtlebot_node/set_digital_outputs", "turtlebot_node/SetDigitalOutputs");
00175                     setDigOutServiceClient.call(setDigOutRequest, new ServiceResponseListener<SetDigitalOutputsResponse>() {
00176                             @Override
00177                             public void onSuccess(final SetDigitalOutputsResponse msg) {
00178                                     numModeResponses++;
00179                                     updateModeWaiting();
00180                             }
00181                             @Override
00182                             public void onFailure(RemoteException e) {
00183                                     numModeResponses++;
00184                                     numModeErrors++;
00185                                     updateModeWaiting();
00186                             }
00187                     });
00188             } catch(Exception ex) {
00189                     Toast.makeText(getContext(), "Exception in service call for set_digital_outputs: " + ex.getMessage(), Toast.LENGTH_LONG).show();
00190                     Log.i("TurtlebotDashboard", "making toast.");
00191             }
00192     }
00193     
00194     private void updateModeWaiting() {
00195             if(numModeResponses >= 2) {
00196                     setModeWaiting(false);
00197             }
00198     }
00199     private void setModeWaiting(final boolean waiting) {
00200             post(new Runnable() {
00201                     @Override
00202                     public void run() {
00203                             modeWaitingSpinner.setVisibility(waiting ? View.VISIBLE : View.GONE);
00204                     }
00205             });
00206     }
00207     private void showMode(String mode) {
00208             if(mode == null) {
00209                     modeButton.setColorFilter(Color.GRAY);
00210             } else if(mode.equals("Full")) {
00211                     modeButton.setColorFilter(Color.GREEN);
00212                     powerOn = true;
00213             } else if(mode.equals("Safe")) {
00214                     modeButton.setColorFilter(Color.YELLOW);
00215                     powerOn = true;
00216             } else if(mode.equals("Passive")) {
00217                     modeButton.setColorFilter(Color.RED);
00218                     powerOn = false;
00219             } else {
00220                     modeButton.setColorFilter(Color.GRAY);
00221                     Log.w("TurtlebotDashboard", "Unknown mode string: '" + mode + "'");
00222             }
00223             setModeWaiting(false);
00224     }
00225     private void populateBatteryFromStatus(BatteryLevelView view, DiagnosticStatus status) {
00226             HashMap<String, String> values = keyValueArrayToMap(status.getValues());
00227             try {
00228                     float percent = 100 * Float.parseFloat(values.get("Charge (Ah)")) / Float.parseFloat(values.get("Capacity (Ah)"));
00229                     view.setBatteryPercent((int) percent);
00230                     // TODO: set color red/yellow/green based on level (maybe with
00231                     // level-set
00232                     // in XML)
00233             } catch(NumberFormatException ex) {
00234                     // TODO: make battery level gray
00235             } catch(ArithmeticException ex) {
00236                     // TODO: make battery level gray
00237             } catch(NullPointerException ex) {
00238                     // Do nothing: data wasn't there.
00239             }
00240             try {
00241                     view.setPluggedIn(Float.parseFloat(values.get("Current (A)")) > 0);
00242             } catch(NumberFormatException ex) {
00243             } catch(ArithmeticException ex) {
00244             } catch(NullPointerException ex) {
00245             }
00246     }
00247     private HashMap<String, String> keyValueArrayToMap(List<KeyValue> list) {
00248             HashMap<String, String> map = new HashMap<String, String>();
00249             for(KeyValue kv : list) {
00250                     map.put(kv.getKey(), kv.getValue());
00251             }
00252             return map;
00253     }
00254     
00255         @Override
00256         public void onShutdown(Node node) {
00257         if(diagnosticSubscriber != null) {
00258             diagnosticSubscriber.shutdown();
00259     }
00260     diagnosticSubscriber = null;
00261     connectedNode = null;
00262                 
00263         }
00264         
00265         @Override
00266         public void onStart(ConnectedNode connectedNode) {
00267 
00268                 this.connectedNode = connectedNode;
00269         try {
00270                 diagnosticSubscriber = connectedNode.newSubscriber("diagnostics_agg", "diagnostic_msgs/DiagnosticArray");
00271                 diagnosticSubscriber.addMessageListener(new MessageListener<diagnostic_msgs.DiagnosticArray>() {
00272                         @Override
00273                         public void onNewMessage(final diagnostic_msgs.DiagnosticArray message) {
00274                                 TurtlebotDashboard.this.post(new Runnable() {
00275                                         @Override
00276                                         public void run() {
00277                                                 TurtlebotDashboard.this.handleDiagnosticArray(message);
00278                                         }
00279                                 });
00280                         }
00281                 });
00282                 NameResolver resolver = connectedNode.getResolver().newChild(GraphName.of("/turtlebot_node"));
00283         } catch(Exception ex) {
00284                 this.connectedNode = null;
00285                 try {
00286                                         throw (new RosException(ex));
00287                                 } catch (RosException e) {
00288                                         // TODO Auto-generated catch block
00289                                         e.printStackTrace();
00290                                 }
00291         }
00292         }
00293 }


turtlebot_android
Author(s):
autogenerated on Wed Aug 26 2015 16:32:04