├── .gitignore ├── AndroidManifest.xml ├── README ├── build.gradle ├── build.xml ├── buildAll.sh ├── local.properties ├── mainpage.dox ├── manifest.xml ├── proguard-project.txt ├── project.properties ├── res ├── color │ └── color.xml ├── drawable-hdpi │ ├── ic_action_help.png │ └── ic_launcher.png ├── drawable-ldpi │ ├── ic_action_help.png │ └── ic_launcher.png ├── drawable-mdpi │ ├── ic_action_help.png │ └── ic_launcher.png ├── drawable-xhdpi │ ├── ic_action_help.png │ └── ic_launcher.png ├── layout │ └── activity_main.xml ├── menu │ └── activity_main.xml ├── values-v11 │ └── styles.xml ├── values-v14 │ └── styles.xml ├── values │ ├── strings.xml │ └── styles.xml └── xml │ └── preferences.xml └── src └── org └── ros └── android └── android_sensors_driver ├── FluidPressurePublisher.java ├── IlluminancePublisher.java ├── ImuPublisher.java ├── MagneticFieldPublisher.java ├── MainActivity.java ├── NavSatFixPublisher.java └── TemperaturePublisher.java /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | ~* 3 | .classpath 4 | .gradle 5 | .project 6 | .settings 7 | bin 8 | build 9 | build.xml 10 | gen 11 | libs 12 | lint.xml 13 | local.properties 14 | proguard-project.txt 15 | project.properties 16 | 17 | # These are Android Studio files, might be worth including these later. 18 | *.iml 19 | .idea 20 | build.log 21 | build-log.xml 22 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Authors: 2 | no email (Tal Regev) 3 | chadrockey@gmail.com (Chad Rockey) 4 | axelfurlan@gmail.com (Axel Furlan) 5 | 6 | This is an extension to the first version of the Ros Android Sensors Driver. 7 | It extends the driver to camera readings and updates the previous version to the post-gradle shift of the rosjava libs. 8 | Two compression methods are currently supported, PNG and JPEG (with selectable compression quality). 9 | The topic names are: 10 | 11 | /android/imu 12 | /android/fix (GPS) 13 | /camera/camera_info 14 | /camera/image/compressed 15 | 16 | 17 | Compiling: 18 | 19 | To compile it on you machine, please follow the detailed instructions at: 20 | 21 | Rosjava: 22 | http://wiki.ros.org/rosjava/Tutorials/indigo/Installation 23 | 24 | Also need to compile android_core from here: 25 | https://github.com/rosjava/android_core/tree/indigo 26 | 27 | Once your environment is set, do the following steps: 28 | 1) git clone the repo in the android_core folder (the same folder where rosjava are ~/rosjava). 29 | 2) Edit the settings.gradle file in the android_core folder, adding 'android_sensors_driver' at the end of the include list. 30 | 3) cd ~/rosjava; catkin_make 31 | 32 | For the whole process of building, packing, installing into the phone and running the app in debug mode, use the buildAll.sh script. 33 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | 19 | dependencies { 20 | compile "org.ros.rosjava_core:rosjava:0.2.0" 21 | compile "org.ros.rosjava_core:rosjava_tutorial_pubsub:[0,)" 22 | compile 'com.android.support:support-v4:21.0.0' 23 | compile project(':android_15') 24 | 25 | } 26 | 27 | 28 | apply plugin: 'android' 29 | 30 | /*debug.dependsOn project(':android_gingerbread_mr1').tasks.debug*/ 31 | 32 | android { 33 | compileSdkVersion 15 34 | 35 | defaultConfig { 36 | minSdkVersion 15 37 | applicationId "org.ros.android.android_sensor_driver" 38 | targetSdkVersion 15 39 | versionCode 1 40 | versionName "1.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 56 | 57 | 69 | 70 | 71 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /buildAll.sh: -------------------------------------------------------------------------------- 1 | # Bash 2 | 3 | ../gradlew clean debug 4 | if [ $? -eq 0 ] 5 | then 6 | adb uninstall org.ros.android.android_sensors_driver 7 | adb install bin/MainActivity-debug.apk 8 | adb shell am start -n org.ros.android.android_sensors_driver/org.ros.android.android_sensors_driver.MainActivity 9 | adb logcat -c 10 | adb logcat 11 | fi 12 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | 7 | # location of the SDK. This is only used by Ant 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir=/home/willow/NVPACK/android-sdk-linux 11 | -------------------------------------------------------------------------------- /mainpage.dox: -------------------------------------------------------------------------------- 1 | /** 2 | \mainpage 3 | \htmlinclude manifest.html 4 | 5 | \b android_sensors_driver is ... 6 | 7 | 10 | 11 | 12 | \section codeapi Code API 13 | 14 | 24 | 25 | 26 | */ 27 | -------------------------------------------------------------------------------- /manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | android_sensors_driver 4 | 5 | Chad Rockey (chadrockey@gmail.com) 6 | Apache 2.0 7 | 8 | http://ros.org/wiki/android_sensors_driver 9 | 10 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-17 12 | #android.library=true 13 | android.library.reference.1=../android_gingerbread_mr1 14 | -------------------------------------------------------------------------------- /res/color/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_action_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-hdpi/ic_action_help.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-ldpi/ic_action_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-ldpi/ic_action_help.png -------------------------------------------------------------------------------- /res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_action_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-mdpi/ic_action_help.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_action_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-xhdpi/ic_action_help.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chadrockey/android_sensors_driver/37b5447081c508223e2d1c99eb2a7a0898a6c879/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /res/menu/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ROS Sensors Driver 5 | 6 | About Android Sensors Driver 7 | Android Sensors Driver is an open source project! For more information, go to the \'Wiki\'. To report bugs or request features click \'Report\'. 8 | OK 9 | Report 10 | Wiki 11 | 12 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 11 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/FluidPressurePublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Chad Rockey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the Android Sensors Driver nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | package org.ros.android.android_sensors_driver; 31 | 32 | 33 | import java.util.List; 34 | 35 | import android.hardware.Sensor; 36 | import android.hardware.SensorEvent; 37 | import android.hardware.SensorEventListener; 38 | import android.hardware.SensorManager; 39 | import android.os.Looper; 40 | import android.os.SystemClock; 41 | 42 | import org.ros.node.ConnectedNode; 43 | import org.ros.message.Time; 44 | import org.ros.namespace.GraphName; 45 | import sensor_msgs.FluidPressure; 46 | import org.ros.node.Node; 47 | import org.ros.node.NodeMain; 48 | import org.ros.node.topic.Publisher; 49 | 50 | /** 51 | * @author chadrockey@gmail.com (Chad Rockey) 52 | */ 53 | public class FluidPressurePublisher implements NodeMain 54 | { 55 | 56 | private FluidPressureThread fpThread; 57 | private SensorListener sensorListener; 58 | private SensorManager sensorManager; 59 | private Publisher publisher; 60 | private int sensorDelay; 61 | 62 | private class FluidPressureThread extends Thread 63 | { 64 | private final SensorManager sensorManager; 65 | private SensorListener sensorListener; 66 | private Looper threadLooper; 67 | 68 | private final Sensor fpSensor; 69 | 70 | private FluidPressureThread(SensorManager sensorManager, SensorListener sensorListener) 71 | { 72 | this.sensorManager = sensorManager; 73 | this.sensorListener = sensorListener; 74 | this.fpSensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE); 75 | } 76 | 77 | 78 | public void run() 79 | { 80 | Looper.prepare(); 81 | this.threadLooper = Looper.myLooper(); 82 | this.sensorManager.registerListener(this.sensorListener, this.fpSensor, sensorDelay); 83 | Looper.loop(); 84 | } 85 | 86 | 87 | public void shutdown() 88 | { 89 | this.sensorManager.unregisterListener(this.sensorListener); 90 | if(this.threadLooper != null) 91 | { 92 | this.threadLooper.quit(); 93 | } 94 | } 95 | } 96 | 97 | private class SensorListener implements SensorEventListener 98 | { 99 | 100 | private Publisher publisher; 101 | 102 | private SensorListener(Publisher publisher) 103 | { 104 | this.publisher = publisher; 105 | } 106 | 107 | // @Override 108 | public void onAccuracyChanged(Sensor sensor, int accuracy) 109 | { 110 | } 111 | 112 | // @Override 113 | public void onSensorChanged(SensorEvent event) 114 | { 115 | if(event.sensor.getType() == Sensor.TYPE_PRESSURE) 116 | { 117 | FluidPressure msg = this.publisher.newMessage(); 118 | long time_delta_millis = System.currentTimeMillis() - SystemClock.uptimeMillis(); 119 | msg.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000)); 120 | msg.getHeader().setFrameId("/imu");// TODO Make parameter 121 | 122 | msg.setFluidPressure(100.0*event.values[0]); // Reported in hPa, need to output in Pa 123 | msg.setVariance(0.0); 124 | 125 | publisher.publish(msg); 126 | } 127 | } 128 | } 129 | 130 | public FluidPressurePublisher(SensorManager manager, int sensorDelay) 131 | { 132 | this.sensorManager = manager; 133 | this.sensorDelay = sensorDelay; 134 | } 135 | 136 | public GraphName getDefaultNodeName() 137 | { 138 | return GraphName.of("android_sensors_driver/fluid_pressure_publisher"); 139 | } 140 | 141 | public void onError(Node node, Throwable throwable) 142 | { 143 | } 144 | 145 | public void onStart(ConnectedNode node) 146 | { 147 | try 148 | { 149 | List mfList = this.sensorManager.getSensorList(Sensor.TYPE_PRESSURE); 150 | 151 | if(mfList.size() > 0) 152 | { 153 | this.publisher = node.newPublisher("android/barometric_pressure", "sensor_msgs/FluidPressure"); 154 | this.sensorListener = new SensorListener(this.publisher); 155 | this.fpThread = new FluidPressureThread(this.sensorManager, this.sensorListener); 156 | this.fpThread.start(); 157 | } 158 | 159 | } 160 | catch (Exception e) 161 | { 162 | if (node != null) 163 | { 164 | node.getLog().fatal(e); 165 | } 166 | else 167 | { 168 | e.printStackTrace(); 169 | } 170 | } 171 | } 172 | 173 | //@Override 174 | public void onShutdown(Node arg0) 175 | { 176 | if(this.fpThread == null){ 177 | return; 178 | } 179 | 180 | this.fpThread.shutdown(); 181 | 182 | try 183 | { 184 | this.fpThread.join(); 185 | } 186 | catch (InterruptedException e) 187 | { 188 | e.printStackTrace(); 189 | } 190 | } 191 | 192 | //@Override 193 | public void onShutdownComplete(Node arg0) 194 | { 195 | } 196 | 197 | } 198 | 199 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/IlluminancePublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Chad Rockey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the Android Sensors Driver nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | package org.ros.android.android_sensors_driver; 31 | 32 | 33 | import java.util.List; 34 | 35 | import android.hardware.Sensor; 36 | import android.hardware.SensorEvent; 37 | import android.hardware.SensorEventListener; 38 | import android.hardware.SensorManager; 39 | import android.os.Looper; 40 | import android.os.SystemClock; 41 | 42 | import org.ros.node.ConnectedNode; 43 | import org.ros.message.Time; 44 | import org.ros.namespace.GraphName; 45 | import sensor_msgs.Illuminance; 46 | import org.ros.node.Node; 47 | import org.ros.node.NodeMain; 48 | import org.ros.node.topic.Publisher; 49 | 50 | /** 51 | * @author chadrockey@gmail.com (Chad Rockey) 52 | */ 53 | public class IlluminancePublisher implements NodeMain 54 | { 55 | 56 | private IlluminanceThread ilThread; 57 | private SensorListener sensorListener; 58 | private SensorManager sensorManager; 59 | private Publisher publisher; 60 | private int sensorDelay; 61 | 62 | private class IlluminanceThread extends Thread 63 | { 64 | private final SensorManager sensorManager; 65 | private SensorListener sensorListener; 66 | private Looper threadLooper; 67 | 68 | private final Sensor ilSensor; 69 | 70 | private IlluminanceThread(SensorManager sensorManager, SensorListener sensorListener) 71 | { 72 | this.sensorManager = sensorManager; 73 | this.sensorListener = sensorListener; 74 | this.ilSensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 75 | } 76 | 77 | 78 | public void run() 79 | { 80 | Looper.prepare(); 81 | this.threadLooper = Looper.myLooper(); 82 | this.sensorManager.registerListener(this.sensorListener, this.ilSensor, sensorDelay); 83 | Looper.loop(); 84 | } 85 | 86 | 87 | public void shutdown() 88 | { 89 | this.sensorManager.unregisterListener(this.sensorListener); 90 | if(this.threadLooper != null) 91 | { 92 | this.threadLooper.quit(); 93 | } 94 | } 95 | } 96 | 97 | private class SensorListener implements SensorEventListener 98 | { 99 | 100 | private Publisher publisher; 101 | 102 | private SensorListener(Publisher publisher) 103 | { 104 | this.publisher = publisher; 105 | } 106 | 107 | // @Override 108 | public void onAccuracyChanged(Sensor sensor, int accuracy) 109 | { 110 | } 111 | 112 | // @Override 113 | public void onSensorChanged(SensorEvent event) 114 | { 115 | if(event.sensor.getType() == Sensor.TYPE_LIGHT) 116 | { 117 | Illuminance msg = this.publisher.newMessage(); 118 | long time_delta_millis = System.currentTimeMillis() - SystemClock.uptimeMillis(); 119 | msg.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000)); 120 | msg.getHeader().setFrameId("android_illuminance"); // TODO Make parameter 121 | 122 | msg.setIlluminance(event.values[0]); 123 | msg.setVariance(0.0); // TODO Make parameter 124 | 125 | publisher.publish(msg); 126 | } 127 | } 128 | } 129 | 130 | public IlluminancePublisher(SensorManager manager, int sensorDelay) 131 | { 132 | this.sensorManager = manager; 133 | this.sensorDelay = sensorDelay; 134 | } 135 | 136 | public GraphName getDefaultNodeName() 137 | { 138 | return GraphName.of("/android/illuminance_publisher"); 139 | } 140 | 141 | public void onError(Node node, Throwable throwable) 142 | { 143 | } 144 | 145 | public void onStart(ConnectedNode node) 146 | { 147 | try 148 | { 149 | List mfList = this.sensorManager.getSensorList(Sensor.TYPE_LIGHT); 150 | 151 | if(mfList.size() > 0) 152 | { 153 | this.publisher = node.newPublisher("android/illuminance", "sensor_msgs/Illuminance"); 154 | this.sensorListener = new SensorListener(this.publisher); 155 | this.ilThread = new IlluminanceThread(this.sensorManager, this.sensorListener); 156 | this.ilThread.start(); 157 | } 158 | 159 | } 160 | catch (Exception e) 161 | { 162 | if (node != null) 163 | { 164 | node.getLog().fatal(e); 165 | } 166 | else 167 | { 168 | e.printStackTrace(); 169 | } 170 | } 171 | } 172 | 173 | //@Override 174 | public void onShutdown(Node arg0) 175 | { 176 | if(this.ilThread == null){ 177 | return; 178 | } 179 | 180 | this.ilThread.shutdown(); 181 | 182 | try 183 | { 184 | this.ilThread.join(); 185 | } 186 | catch (InterruptedException e) 187 | { 188 | e.printStackTrace(); 189 | } 190 | } 191 | 192 | //@Override 193 | public void onShutdownComplete(Node arg0) 194 | { 195 | } 196 | 197 | } 198 | 199 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/ImuPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Chad Rockey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the Android Sensors Driver nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | package org.ros.android.android_sensors_driver; 31 | 32 | 33 | import java.util.List; 34 | import android.hardware.Sensor; 35 | import android.hardware.SensorEvent; 36 | import android.hardware.SensorEventListener; 37 | import android.hardware.SensorManager; 38 | import android.os.Looper; 39 | import android.os.SystemClock; 40 | 41 | import org.ros.node.ConnectedNode; 42 | import org.ros.message.Time; 43 | import org.ros.namespace.GraphName; 44 | import sensor_msgs.Imu; 45 | import org.ros.node.Node; 46 | import org.ros.node.NodeMain; 47 | import org.ros.node.topic.Publisher; 48 | 49 | /** 50 | * @author chadrockey@gmail.com (Chad Rockey) 51 | * @author axelfurlan@gmail.com (Axel Furlan) 52 | */ 53 | public class ImuPublisher implements NodeMain 54 | { 55 | 56 | private ImuThread imuThread; 57 | private SensorListener sensorListener; 58 | private SensorManager sensorManager; 59 | private Publisher publisher; 60 | private int sensorDelay; 61 | 62 | private class ImuThread extends Thread 63 | { 64 | private final SensorManager sensorManager; 65 | private SensorListener sensorListener; 66 | private Looper threadLooper; 67 | 68 | private final Sensor accelSensor; 69 | private final Sensor gyroSensor; 70 | private final Sensor quatSensor; 71 | 72 | private ImuThread(SensorManager sensorManager, SensorListener sensorListener) 73 | { 74 | this.sensorManager = sensorManager; 75 | this.sensorListener = sensorListener; 76 | this.accelSensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 77 | this.gyroSensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 78 | this.quatSensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); 79 | } 80 | 81 | 82 | public void run() 83 | { 84 | Looper.prepare(); 85 | this.threadLooper = Looper.myLooper(); 86 | this.sensorManager.registerListener(this.sensorListener, this.accelSensor, sensorDelay); 87 | this.sensorManager.registerListener(this.sensorListener, this.gyroSensor, sensorDelay); 88 | this.sensorManager.registerListener(this.sensorListener, this.quatSensor, sensorDelay); 89 | Looper.loop(); 90 | } 91 | 92 | 93 | public void shutdown() 94 | { 95 | this.sensorManager.unregisterListener(this.sensorListener); 96 | if(this.threadLooper != null) 97 | { 98 | this.threadLooper.quit(); 99 | } 100 | } 101 | } 102 | 103 | private class SensorListener implements SensorEventListener 104 | { 105 | 106 | private Publisher publisher; 107 | 108 | private boolean hasAccel; 109 | private boolean hasGyro; 110 | private boolean hasQuat; 111 | 112 | private long accelTime; 113 | private long gyroTime; 114 | private long quatTime; 115 | 116 | private Imu imu; 117 | 118 | private SensorListener(Publisher publisher, boolean hasAccel, boolean hasGyro, boolean hasQuat) 119 | { 120 | this.publisher = publisher; 121 | this.hasAccel = hasAccel; 122 | this.hasGyro = hasGyro; 123 | this.hasQuat = hasQuat; 124 | this.accelTime = 0; 125 | this.gyroTime = 0; 126 | this.quatTime = 0; 127 | this.imu = this.publisher.newMessage(); 128 | } 129 | 130 | // @Override 131 | public void onAccuracyChanged(Sensor sensor, int accuracy) 132 | { 133 | } 134 | 135 | // @Override 136 | public void onSensorChanged(SensorEvent event) 137 | { 138 | if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) 139 | { 140 | this.imu.getLinearAcceleration().setX(event.values[0]); 141 | this.imu.getLinearAcceleration().setY(event.values[1]); 142 | this.imu.getLinearAcceleration().setZ(event.values[2]); 143 | 144 | double[] tmpCov = {0,0,0, 0,0,0, 0,0,0};// TODO Make Parameter 145 | this.imu.setLinearAccelerationCovariance(tmpCov); 146 | this.accelTime = event.timestamp; 147 | } 148 | else if(event.sensor.getType() == Sensor.TYPE_GYROSCOPE) 149 | { 150 | this.imu.getAngularVelocity().setX(event.values[0]); 151 | this.imu.getAngularVelocity().setY(event.values[1]); 152 | this.imu.getAngularVelocity().setZ(event.values[2]); 153 | double[] tmpCov = {0,0,0, 0,0,0, 0,0,0};// TODO Make Parameter 154 | this.imu.setAngularVelocityCovariance(tmpCov); 155 | this.gyroTime = event.timestamp; 156 | } 157 | else if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) 158 | { 159 | float[] quaternion = new float[4]; 160 | SensorManager.getQuaternionFromVector(quaternion, event.values); 161 | this.imu.getOrientation().setW(quaternion[0]); 162 | this.imu.getOrientation().setX(quaternion[1]); 163 | this.imu.getOrientation().setY(quaternion[2]); 164 | this.imu.getOrientation().setZ(quaternion[3]); 165 | double[] tmpCov = {0,0,0, 0,0,0, 0,0,0};// TODO Make Parameter 166 | this.imu.setOrientationCovariance(tmpCov); 167 | this.quatTime = event.timestamp; 168 | } 169 | 170 | // Currently storing event times in case I filter them in the future. Otherwise they are used to determine if all sensors have reported. 171 | if((this.accelTime != 0 || !this.hasAccel) && 172 | (this.gyroTime != 0 || !this.hasGyro) && 173 | (this.quatTime != 0 || !this.hasQuat)) 174 | { 175 | // Convert event.timestamp (nanoseconds uptime) into system time, use that as the header stamp 176 | long time_delta_millis = System.currentTimeMillis() - SystemClock.uptimeMillis(); 177 | this.imu.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000)); 178 | this.imu.getHeader().setFrameId("/imu");// TODO Make parameter 179 | 180 | publisher.publish(this.imu); 181 | 182 | // Create a new message 183 | this.imu = this.publisher.newMessage(); 184 | 185 | // Reset times 186 | this.accelTime = 0; 187 | this.gyroTime = 0; 188 | this.quatTime = 0; 189 | } 190 | } 191 | } 192 | 193 | 194 | public ImuPublisher(SensorManager manager, int sensorDelay) 195 | { 196 | this.sensorManager = manager; 197 | this.sensorDelay = sensorDelay; 198 | } 199 | 200 | public GraphName getDefaultNodeName() 201 | { 202 | return GraphName.of("android_sensors_driver/imuPublisher"); 203 | } 204 | 205 | public void onError(Node node, Throwable throwable) 206 | { 207 | } 208 | 209 | public void onStart(ConnectedNode node) 210 | { 211 | try 212 | { 213 | this.publisher = node.newPublisher("android/imu", "sensor_msgs/Imu"); 214 | // Determine if we have the various needed sensors 215 | boolean hasAccel = false; 216 | boolean hasGyro = false; 217 | boolean hasQuat = false; 218 | 219 | List accelList = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); 220 | 221 | if(accelList.size() > 0) 222 | { 223 | hasAccel = true; 224 | } 225 | 226 | List gyroList = this.sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE); 227 | if(gyroList.size() > 0) 228 | { 229 | hasGyro = true; 230 | } 231 | 232 | List quatList = this.sensorManager.getSensorList(Sensor.TYPE_ROTATION_VECTOR); 233 | if(quatList.size() > 0) 234 | { 235 | hasQuat = true; 236 | } 237 | 238 | this.sensorListener = new SensorListener(publisher, hasAccel, hasGyro, hasQuat); 239 | this.imuThread = new ImuThread(this.sensorManager, sensorListener); 240 | this.imuThread.start(); 241 | } 242 | catch (Exception e) 243 | { 244 | if (node != null) 245 | { 246 | node.getLog().fatal(e); 247 | } 248 | else 249 | { 250 | e.printStackTrace(); 251 | } 252 | } 253 | } 254 | 255 | //@Override 256 | public void onShutdown(Node arg0) 257 | { 258 | if(this.imuThread == null){ 259 | return; 260 | } 261 | this.imuThread.shutdown(); 262 | 263 | try 264 | { 265 | this.imuThread.join(); 266 | } 267 | catch (InterruptedException e) 268 | { 269 | e.printStackTrace(); 270 | } 271 | } 272 | 273 | //@Override 274 | public void onShutdownComplete(Node arg0) 275 | { 276 | } 277 | 278 | } 279 | 280 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/MagneticFieldPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Chad Rockey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the Android Sensors Driver nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | package org.ros.android.android_sensors_driver; 31 | 32 | 33 | import java.util.List; 34 | 35 | import android.hardware.Sensor; 36 | import android.hardware.SensorEvent; 37 | import android.hardware.SensorEventListener; 38 | import android.hardware.SensorManager; 39 | import android.os.Looper; 40 | import android.os.SystemClock; 41 | 42 | import org.ros.node.ConnectedNode; 43 | import org.ros.message.Time; 44 | import org.ros.namespace.GraphName; 45 | import sensor_msgs.MagneticField; 46 | import org.ros.node.Node; 47 | import org.ros.node.NodeMain; 48 | import org.ros.node.topic.Publisher; 49 | 50 | /** 51 | * @author chadrockey@gmail.com (Chad Rockey) 52 | */ 53 | public class MagneticFieldPublisher implements NodeMain 54 | { 55 | 56 | private MagneticFieldThread mfThread; 57 | private SensorListener sensorListener; 58 | private SensorManager sensorManager; 59 | private Publisher publisher; 60 | private int sensorDelay; 61 | 62 | private class MagneticFieldThread extends Thread 63 | { 64 | private final SensorManager sensorManager; 65 | private SensorListener sensorListener; 66 | private Looper threadLooper; 67 | 68 | 69 | private final Sensor mfSensor; 70 | 71 | private MagneticFieldThread(SensorManager sensorManager, SensorListener sensorListener) 72 | { 73 | this.sensorManager = sensorManager; 74 | this.sensorListener = sensorListener; 75 | this.mfSensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 76 | } 77 | 78 | 79 | public void run() 80 | { 81 | Looper.prepare(); 82 | this.threadLooper = Looper.myLooper(); 83 | this.sensorManager.registerListener(this.sensorListener, this.mfSensor, sensorDelay); 84 | Looper.loop(); 85 | } 86 | 87 | 88 | public void shutdown() 89 | { 90 | this.sensorManager.unregisterListener(this.sensorListener); 91 | if(this.threadLooper != null) 92 | { 93 | this.threadLooper.quit(); 94 | } 95 | } 96 | } 97 | 98 | private class SensorListener implements SensorEventListener 99 | { 100 | 101 | private Publisher publisher; 102 | 103 | private SensorListener(Publisher publisher) 104 | { 105 | this.publisher = publisher; 106 | } 107 | 108 | // @Override 109 | public void onAccuracyChanged(Sensor sensor, int accuracy) 110 | { 111 | } 112 | 113 | // @Override 114 | public void onSensorChanged(SensorEvent event) 115 | { 116 | if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) 117 | { 118 | MagneticField msg = this.publisher.newMessage(); 119 | long time_delta_millis = System.currentTimeMillis() - SystemClock.uptimeMillis(); 120 | msg.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000)); 121 | msg.getHeader().setFrameId("/imu");// TODO Make parameter 122 | 123 | msg.getMagneticField().setX(event.values[0]/1e6); 124 | msg.getMagneticField().setY(event.values[1]/1e6); 125 | msg.getMagneticField().setZ(event.values[2]/1e6); 126 | 127 | double[] tmpCov = {0,0,0, 0,0,0, 0,0,0}; // TODO Make Parameter 128 | msg.setMagneticFieldCovariance(tmpCov); 129 | 130 | publisher.publish(msg); 131 | } 132 | } 133 | } 134 | 135 | 136 | public MagneticFieldPublisher(SensorManager manager, int sensorDelay) 137 | { 138 | this.sensorManager = manager; 139 | this.sensorDelay = sensorDelay; 140 | } 141 | 142 | public GraphName getDefaultNodeName() 143 | { 144 | return GraphName.of("android_sensors_driver/magnetic_field_publisher"); 145 | } 146 | 147 | public void onError(Node node, Throwable throwable) 148 | { 149 | } 150 | 151 | public void onStart(ConnectedNode node) 152 | { 153 | try 154 | { 155 | List mfList = this.sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD); 156 | 157 | if(mfList.size() > 0) 158 | { 159 | this.publisher = node.newPublisher("android/magnetic_field", "sensor_msgs/MagneticField"); 160 | this.sensorListener = new SensorListener(this.publisher); 161 | this.mfThread = new MagneticFieldThread(this.sensorManager, this.sensorListener); 162 | this.mfThread.start(); 163 | } 164 | 165 | } 166 | catch (Exception e) 167 | { 168 | if (node != null) 169 | { 170 | node.getLog().fatal(e); 171 | } 172 | else 173 | { 174 | e.printStackTrace(); 175 | } 176 | } 177 | } 178 | 179 | //@Override 180 | public void onShutdown(Node arg0) 181 | { 182 | if(this.mfThread == null){ 183 | return; 184 | } 185 | 186 | this.mfThread.shutdown(); 187 | 188 | try 189 | { 190 | this.mfThread.join(); 191 | } 192 | catch (InterruptedException e) 193 | { 194 | e.printStackTrace(); 195 | } 196 | } 197 | 198 | //@Override 199 | public void onShutdownComplete(Node arg0) 200 | { 201 | } 202 | 203 | } 204 | 205 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.ros.android.android_sensors_driver; 18 | 19 | import android.app.AlertDialog; 20 | import android.content.ActivityNotFoundException; 21 | import android.content.Context; 22 | import android.content.DialogInterface; 23 | import android.content.Intent; 24 | import android.hardware.Sensor; 25 | import android.hardware.SensorManager; 26 | import android.location.LocationManager; 27 | import android.net.Uri; 28 | import android.os.Bundle; 29 | import android.widget.Toast; 30 | 31 | import org.ros.address.InetAddressFactory; 32 | import org.ros.android.RosActivity; 33 | import org.ros.node.NodeConfiguration; 34 | import org.ros.node.NodeMainExecutor; 35 | 36 | import android.view.Menu; 37 | import android.view.MenuItem; 38 | import android.view.SubMenu; 39 | import android.view.Window; 40 | import android.view.WindowManager; 41 | import android.view.MenuInflater; 42 | 43 | import java.net.URI; 44 | 45 | /** 46 | * @author chadrockey@gmail.com (Chad Rockey) 47 | * @author axelfurlan@gmail.com (Axel Furlan) 48 | */ 49 | 50 | 51 | public class MainActivity extends RosActivity 52 | { 53 | private NavSatFixPublisher fix_pub; 54 | private ImuPublisher imu_pub; 55 | private MagneticFieldPublisher magnetic_field_pub; 56 | private FluidPressurePublisher fluid_pressure_pub; 57 | private IlluminancePublisher illuminance_pub; 58 | private TemperaturePublisher temperature_pub; 59 | 60 | private LocationManager mLocationManager; 61 | private SensorManager mSensorManager; 62 | 63 | 64 | public MainActivity() 65 | { 66 | super("ROS Sensors Driver", "ROS Sensors Driver"); 67 | } 68 | 69 | @Override 70 | protected void onPause() 71 | { 72 | super.onPause(); 73 | } 74 | 75 | @Override 76 | protected void onCreate(Bundle savedInstanceState) 77 | { 78 | super.onCreate(savedInstanceState); 79 | setContentView(R.layout.activity_main); 80 | 81 | mLocationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE); 82 | mSensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE); 83 | } 84 | 85 | @Override 86 | protected void onResume() 87 | { 88 | super.onResume(); 89 | } 90 | 91 | 92 | @Override 93 | protected void init(NodeMainExecutor nodeMainExecutor) 94 | { 95 | URI masterURI = getMasterUri(); 96 | //masterURI = URI.create("http://192.168.15.247:11311/"); 97 | //masterURI = URI.create("http://10.0.1.157:11311/"); 98 | 99 | int currentapiVersion = android.os.Build.VERSION.SDK_INT; 100 | 101 | int sensorDelay = 20000; // 20,000 us == 50 Hz for Android 3.1 and above 102 | if(currentapiVersion <= android.os.Build.VERSION_CODES.HONEYCOMB){ 103 | sensorDelay = SensorManager.SENSOR_DELAY_UI; // 16.7Hz for older devices. They only support enum values, not the microsecond version. 104 | } 105 | 106 | @SuppressWarnings("deprecation") 107 | int tempSensor = Sensor.TYPE_TEMPERATURE; // Older temperature 108 | if(currentapiVersion <= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){ 109 | tempSensor = Sensor.TYPE_AMBIENT_TEMPERATURE; // Use newer temperature if possible 110 | } 111 | 112 | 113 | if(currentapiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD){ 114 | NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); 115 | nodeConfiguration.setMasterUri(masterURI); 116 | nodeConfiguration.setNodeName("android_sensors_driver_magnetic_field"); 117 | this.magnetic_field_pub = new MagneticFieldPublisher(mSensorManager, sensorDelay); 118 | nodeMainExecutor.execute(this.magnetic_field_pub, nodeConfiguration); 119 | } 120 | 121 | if(currentapiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD){ 122 | NodeConfiguration nodeConfiguration2 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); 123 | nodeConfiguration2.setMasterUri(masterURI); 124 | nodeConfiguration2.setNodeName("android_sensors_driver_nav_sat_fix"); 125 | this.fix_pub = new NavSatFixPublisher(mLocationManager); 126 | nodeMainExecutor.execute(this.fix_pub, nodeConfiguration2); 127 | } 128 | 129 | if(currentapiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD){ 130 | NodeConfiguration nodeConfiguration3 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); 131 | nodeConfiguration3.setMasterUri(masterURI); 132 | nodeConfiguration3.setNodeName("android_sensors_driver_imu"); 133 | this.imu_pub = new ImuPublisher(mSensorManager, sensorDelay); 134 | nodeMainExecutor.execute(this.imu_pub, nodeConfiguration3); 135 | } 136 | 137 | if(currentapiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD){ 138 | NodeConfiguration nodeConfiguration4 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); 139 | nodeConfiguration4.setMasterUri(masterURI); 140 | nodeConfiguration4.setNodeName("android_sensors_driver_pressure"); 141 | this.fluid_pressure_pub = new FluidPressurePublisher(mSensorManager, sensorDelay); 142 | nodeMainExecutor.execute(this.fluid_pressure_pub, nodeConfiguration4); 143 | } 144 | 145 | if(currentapiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD){ 146 | NodeConfiguration nodeConfiguration5 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); 147 | nodeConfiguration5.setMasterUri(masterURI); 148 | nodeConfiguration5.setNodeName("android_sensors_driver_illuminance"); 149 | this.illuminance_pub = new IlluminancePublisher(mSensorManager, sensorDelay); 150 | nodeMainExecutor.execute(this.illuminance_pub, nodeConfiguration5); 151 | } 152 | 153 | if(currentapiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD){ 154 | NodeConfiguration nodeConfiguration6 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); 155 | nodeConfiguration6.setMasterUri(masterURI); 156 | nodeConfiguration6.setNodeName("android_sensors_driver_temperature"); 157 | this.temperature_pub = new TemperaturePublisher(mSensorManager, sensorDelay, tempSensor); 158 | nodeMainExecutor.execute(this.temperature_pub, nodeConfiguration6); 159 | } 160 | } 161 | 162 | @Override 163 | public boolean onCreateOptionsMenu(Menu menu) { 164 | MenuInflater inflater = getMenuInflater(); 165 | inflater.inflate(R.menu.activity_main, menu); 166 | return super.onCreateOptionsMenu(menu); 167 | } 168 | 169 | @Override 170 | public boolean onOptionsItemSelected(MenuItem item) { 171 | if(item.getItemId() == R.id.menu_help) { 172 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 173 | builder.setCancelable(true); 174 | builder.setTitle(getResources().getString(R.string.help_title)); 175 | builder.setMessage(getResources().getString(R.string.help_message)); 176 | builder.setInverseBackgroundForced(true); 177 | builder.setNegativeButton(getResources().getString(R.string.help_ok), 178 | new DialogInterface.OnClickListener() { 179 | @Override 180 | public void onClick(DialogInterface dialog, int which) { 181 | dialog.dismiss(); 182 | } 183 | }); 184 | builder.setNeutralButton(getResources().getString(R.string.help_wiki), 185 | new DialogInterface.OnClickListener() { 186 | @Override 187 | public void onClick(DialogInterface dialog, int which) { 188 | Intent i = new Intent(Intent.ACTION_VIEW); 189 | Uri u = Uri.parse("http://www.ros.org/wiki/android_sensors_driver"); 190 | try { 191 | // Start the activity 192 | i.setData(u); 193 | startActivity(i); 194 | } catch (ActivityNotFoundException e) { 195 | // Raise on activity not found 196 | Toast toast = Toast.makeText(MainActivity.this, "Browser not found.", Toast.LENGTH_SHORT); 197 | toast.show(); 198 | } 199 | } 200 | }); 201 | builder.setPositiveButton(getResources().getString(R.string.help_report), 202 | new DialogInterface.OnClickListener() { 203 | @Override 204 | public void onClick(DialogInterface dialog, int which) { 205 | Intent i = new Intent(Intent.ACTION_VIEW); 206 | Uri u = Uri.parse("https://github.com/ros-android/android_sensors_driver/issues/new"); 207 | try { 208 | // Start the activity 209 | i.setData(u); 210 | startActivity(i); 211 | } catch (ActivityNotFoundException e) { 212 | // Raise on activity not found 213 | Toast toast = Toast.makeText(MainActivity.this, "Browser not found.", Toast.LENGTH_SHORT); 214 | toast.show(); 215 | } 216 | } 217 | }); 218 | AlertDialog alert = builder.create(); 219 | alert.show(); 220 | 221 | } 222 | return super.onOptionsItemSelected(item); 223 | } 224 | } 225 | 226 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/NavSatFixPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Chad Rockey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the Android Sensors Driver nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | package org.ros.android.android_sensors_driver; 31 | 32 | import android.location.Location; 33 | import android.location.LocationListener; 34 | import android.location.LocationManager; 35 | import android.location.LocationProvider; 36 | import android.os.Bundle; 37 | import android.os.Looper; 38 | 39 | import org.ros.namespace.GraphName; 40 | import org.ros.node.ConnectedNode; 41 | import org.ros.message.Time; 42 | import sensor_msgs.NavSatFix; 43 | import sensor_msgs.NavSatStatus; 44 | import org.ros.node.Node; 45 | import org.ros.node.NodeMain; 46 | import org.ros.node.topic.Publisher; 47 | 48 | /** 49 | * @author chadrockey@gmail.com (Chad Rockey) 50 | * @author axelfurlan@gmail.com (Axel Furlan) 51 | */ 52 | public class NavSatFixPublisher implements NodeMain { 53 | 54 | private NavSatThread navSatThread; 55 | private LocationManager locationManager; 56 | private NavSatListener navSatFixListener; 57 | private Publisher publisher; 58 | 59 | private class NavSatThread extends Thread { 60 | LocationManager locationManager; 61 | NavSatListener navSatListener; 62 | private Looper threadLooper; 63 | 64 | private NavSatThread(LocationManager locationManager, NavSatListener navSatListener){ 65 | this.locationManager = locationManager; 66 | this.navSatListener = navSatListener; 67 | } 68 | 69 | public void run() { 70 | Looper.prepare(); 71 | threadLooper = Looper.myLooper(); 72 | this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this.navSatListener); 73 | Looper.loop(); 74 | } 75 | 76 | public void shutdown(){ 77 | this.locationManager.removeUpdates(this.navSatListener); 78 | if(threadLooper != null){ 79 | threadLooper.quit(); 80 | } 81 | } 82 | } 83 | 84 | private class NavSatListener implements LocationListener { 85 | 86 | private Publisher publisher; 87 | 88 | private volatile byte currentStatus; 89 | 90 | private NavSatListener(Publisher publisher) { 91 | this.publisher = publisher; 92 | this.currentStatus = NavSatStatus.STATUS_FIX; // Default to fix until we are told otherwise. 93 | } 94 | 95 | // @Override 96 | public void onLocationChanged(Location location) 97 | { 98 | NavSatFix fix = this.publisher.newMessage(); 99 | fix.getHeader().setStamp(Time.fromMillis(System.currentTimeMillis())); 100 | fix.getHeader().setFrameId("/gps"); 101 | 102 | fix.getStatus().setStatus(currentStatus); 103 | fix.getStatus().setService(NavSatStatus.SERVICE_GPS); 104 | 105 | fix.setLatitude(location.getLatitude()); 106 | fix.setLongitude(location.getLongitude()); 107 | fix.setAltitude(location.getAltitude()); 108 | fix.setPositionCovarianceType(NavSatFix.COVARIANCE_TYPE_APPROXIMATED); 109 | double deviation = location.getAccuracy(); 110 | double covariance = deviation*deviation; 111 | double[] tmpCov = {covariance,0,0, 0,covariance,0, 0,0,covariance}; 112 | fix.setPositionCovariance(tmpCov); 113 | publisher.publish(fix); 114 | } 115 | 116 | // @Override 117 | public void onProviderDisabled(String provider) { 118 | } 119 | 120 | // @Override 121 | public void onProviderEnabled(String provider) { 122 | } 123 | 124 | // @Override 125 | public void onStatusChanged(String provider, int status, Bundle extras) { 126 | switch (status) { 127 | case LocationProvider.OUT_OF_SERVICE: 128 | currentStatus = NavSatStatus.STATUS_NO_FIX; 129 | break; 130 | case LocationProvider.TEMPORARILY_UNAVAILABLE: 131 | currentStatus = NavSatStatus.STATUS_NO_FIX; 132 | break; 133 | case LocationProvider.AVAILABLE: 134 | currentStatus = NavSatStatus.STATUS_FIX; 135 | break; 136 | } 137 | } 138 | } 139 | 140 | public NavSatFixPublisher(LocationManager manager) { 141 | this.locationManager = manager; 142 | } 143 | 144 | //@Override 145 | public void onStart(ConnectedNode node) 146 | { 147 | try 148 | { 149 | this.publisher = node.newPublisher("android/fix", "sensor_msgs/NavSatFix"); 150 | this.navSatFixListener = new NavSatListener(publisher); 151 | this.navSatThread = new NavSatThread(this.locationManager, this.navSatFixListener); 152 | this.navSatThread.start(); 153 | } 154 | catch (Exception e) 155 | { 156 | if (node != null) 157 | { 158 | node.getLog().fatal(e); 159 | } 160 | else 161 | { 162 | e.printStackTrace(); 163 | } 164 | } 165 | } 166 | 167 | //@Override 168 | public void onShutdown(Node arg0) { 169 | if(this.navSatThread == null){ 170 | return; 171 | } 172 | 173 | this.navSatThread.shutdown(); 174 | try { 175 | this.navSatThread.join(); 176 | } catch (InterruptedException e) { 177 | e.printStackTrace(); 178 | } 179 | } 180 | 181 | //@Override 182 | public void onShutdownComplete(Node arg0) { 183 | } 184 | 185 | public GraphName getDefaultNodeName() 186 | { 187 | return GraphName.of("android_sensors_driver/imuPublisher"); 188 | } 189 | 190 | public void onError(Node node, Throwable throwable) 191 | { 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /src/org/ros/android/android_sensors_driver/TemperaturePublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Chad Rockey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the Android Sensors Driver nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | package org.ros.android.android_sensors_driver; 31 | 32 | 33 | import java.util.List; 34 | 35 | import android.hardware.Sensor; 36 | import android.hardware.SensorEvent; 37 | import android.hardware.SensorEventListener; 38 | import android.hardware.SensorManager; 39 | import android.os.Looper; 40 | import android.os.SystemClock; 41 | 42 | import org.ros.node.ConnectedNode; 43 | import org.ros.message.Time; 44 | import org.ros.namespace.GraphName; 45 | import sensor_msgs.Temperature; 46 | import org.ros.node.Node; 47 | import org.ros.node.NodeMain; 48 | import org.ros.node.topic.Publisher; 49 | 50 | /** 51 | * @author chadrockey@gmail.com (Chad Rockey) 52 | */ 53 | public class TemperaturePublisher implements NodeMain 54 | { 55 | 56 | private TemperatureThread tmpThread; 57 | private SensorListener sensorListener; 58 | private SensorManager sensorManager; 59 | private Publisher publisher; 60 | private int sensorType; 61 | private int sensorDelay; 62 | 63 | private class TemperatureThread extends Thread 64 | { 65 | private final SensorManager sensorManager; 66 | private SensorListener sensorListener; 67 | private Looper threadLooper; 68 | 69 | 70 | private final Sensor tmpSensor; 71 | 72 | private TemperatureThread(SensorManager sensorManager, SensorListener sensorListener) 73 | { 74 | this.sensorManager = sensorManager; 75 | this.sensorListener = sensorListener; 76 | this.tmpSensor = this.sensorManager.getDefaultSensor(sensorType); 77 | } 78 | 79 | 80 | public void run() 81 | { 82 | Looper.prepare(); 83 | this.threadLooper = Looper.myLooper(); 84 | this.sensorManager.registerListener(this.sensorListener, this.tmpSensor, sensorDelay); 85 | Looper.loop(); 86 | } 87 | 88 | 89 | public void shutdown() 90 | { 91 | this.sensorManager.unregisterListener(this.sensorListener); 92 | if(this.threadLooper != null) 93 | { 94 | this.threadLooper.quit(); 95 | } 96 | } 97 | } 98 | 99 | private class SensorListener implements SensorEventListener 100 | { 101 | 102 | private Publisher publisher; 103 | 104 | private SensorListener(Publisher publisher) 105 | { 106 | this.publisher = publisher; 107 | } 108 | 109 | // @Override 110 | public void onAccuracyChanged(Sensor sensor, int accuracy) 111 | { 112 | } 113 | 114 | // @Override 115 | public void onSensorChanged(SensorEvent event) 116 | { 117 | if(event.sensor.getType() == sensorType) 118 | { 119 | Temperature msg = this.publisher.newMessage(); 120 | long time_delta_millis = System.currentTimeMillis() - SystemClock.uptimeMillis(); 121 | msg.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000)); 122 | msg.getHeader().setFrameId("/android/temperature");// TODO Make parameter 123 | 124 | msg.setTemperature(event.values[0]); 125 | msg.setVariance(0.0); 126 | 127 | this.publisher.publish(msg); 128 | } 129 | } 130 | } 131 | 132 | public TemperaturePublisher(SensorManager manager, int sensorDelay, int sensorType) 133 | { 134 | this.sensorManager = manager; 135 | this.sensorDelay = sensorDelay; 136 | this.sensorType = sensorType; 137 | } 138 | 139 | public GraphName getDefaultNodeName() 140 | { 141 | return GraphName.of("android_sensors_driver/temperature_publisher"); 142 | } 143 | 144 | public void onError(Node node, Throwable throwable) 145 | { 146 | } 147 | 148 | public void onStart(ConnectedNode node) 149 | { 150 | try 151 | { 152 | List mfList = this.sensorManager.getSensorList(sensorType); 153 | 154 | if(mfList.size() > 0) 155 | { 156 | this.publisher = node.newPublisher("android/temperature", "sensor_msgs/Temperature"); 157 | this.sensorListener = new SensorListener(this.publisher); 158 | this.tmpThread = new TemperatureThread(this.sensorManager, this.sensorListener); 159 | this.tmpThread.start(); 160 | } 161 | 162 | } 163 | catch (Exception e) 164 | { 165 | if (node != null) 166 | { 167 | node.getLog().fatal(e); 168 | } 169 | else 170 | { 171 | e.printStackTrace(); 172 | } 173 | } 174 | } 175 | 176 | //@Override 177 | public void onShutdown(Node arg0) 178 | { 179 | if(this.tmpThread == null){ 180 | return; 181 | } 182 | 183 | this.tmpThread.shutdown(); 184 | 185 | try 186 | { 187 | this.tmpThread.join(); 188 | } 189 | catch (InterruptedException e) 190 | { 191 | e.printStackTrace(); 192 | } 193 | } 194 | 195 | //@Override 196 | public void onShutdownComplete(Node arg0) 197 | { 198 | } 199 | 200 | } 201 | 202 | --------------------------------------------------------------------------------