├── AndroidManifest.xml
├── README
├── build.gradle
├── build.xml
├── buildAll.sh
├── local.properties
├── mainpage.dox
├── manifest.xml
├── proguard-project.txt
├── project.properties
├── res
├── layout
│ └── main.xml
└── values
│ └── strings.xml
└── src
└── org
└── ros
└── android
└── android_sensors_driver
├── ImuPublisher.java
├── MainActivity.java
└── NavSatFixPublisher.java
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Authors:
2 | chadrockey@gmail.com (Chad Rockey)
3 | axelfurlan@gmail.com (Axel Furlan)
4 |
5 | This is an extension to the first version of the Ros Android Sensors Driver.
6 | It extends the driver to camera readings and updates the previous version to the post-gradle shift of the rosjava libs.
7 | Two compression methods are currently supported, PNG and JPEG (with selectable compression quality).
8 | The topic names are:
9 |
10 | /android/imu
11 | /android/fix (GPS)
12 | /camera/camera_info
13 | /camera/image/compressed
14 |
15 |
16 |
17 |
18 | Compiling:
19 |
20 | To compile it on you machine, please follow the detailed instructions at:
21 |
22 | Rosjava:
23 | http://www.dobots.nl/blog/-/blogs/android-and-rosjava
24 |
25 | Once your environment is set, do the following steps:
26 | 1) git clone the repo in the android_core folder (the same folder where tutorials are).
27 | 2) Edit the settings.gradle file in the android_core folder, adding 'android_sensors_driver' at the end of the include list.
28 | 3) cd android_sensors_driver; ../gradlew clean debug
29 |
30 | For the whole process of building, packing, installing into the phone and running the app in debug mode, use the buildAll.sh script.
--------------------------------------------------------------------------------
/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 | dependencies {
18 | compile 'ros.rosjava_core:rosjava_tutorial_pubsub:0.0.0-SNAPSHOT'
19 | }
20 |
21 |
22 | debug.dependsOn project(':android_gingerbread_mr1').tasks.debug
23 |
24 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
40 |
41 |
42 |
43 |
47 |
48 |
60 |
61 |
62 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/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-13
12 | #android.library=true
13 | android.library.reference.1=../android_gingerbread_mr1
14 | android.library.reference.2=../../OpenCV-2.4.2-android-sdk/sdk/java
15 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
17 |
18 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ROS Android Sensors Driver
4 |
5 |
--------------------------------------------------------------------------------
/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 |
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.Imu;
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 | * @author axelfurlan@gmail.com (Axel Furlan)
53 | */
54 | public class ImuPublisher implements NodeMain
55 | {
56 |
57 | private ImuThread imuThread;
58 | private SensorListener sensorListener;
59 | private SensorManager sensorManager;
60 | private Publisher publisher;
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, SensorManager.SENSOR_DELAY_FASTEST);
87 | this.sensorManager.registerListener(this.sensorListener, this.gyroSensor, SensorManager.SENSOR_DELAY_FASTEST);
88 | this.sensorManager.registerListener(this.sensorListener, this.quatSensor, SensorManager.SENSOR_DELAY_FASTEST);
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.01,0,0, 0,0.01,0, 0,0,0.01};// 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.0025,0,0, 0,0.0025,0, 0,0,0.0025};// 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.001,0,0, 0,0.001,0, 0,0,0.001};// 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) && (this.gyroTime != 0 || !this.hasGyro) && (this.quatTime != 0 || !this.hasQuat))
172 | {
173 | // Convert event.timestamp (nanoseconds uptime) into system time, use that as the header stamp
174 | long time_delta_millis = System.currentTimeMillis() - SystemClock.uptimeMillis();
175 | this.imu.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000));
176 | this.imu.getHeader().setFrameId("/imu");// TODO Make parameter
177 |
178 | publisher.publish(this.imu);
179 |
180 | // Create a new message
181 | this.imu = this.publisher.newMessage();
182 |
183 | // Reset times
184 | this.accelTime = 0;
185 | this.gyroTime = 0;
186 | this.quatTime = 0;
187 | }
188 | }
189 | }
190 |
191 |
192 | public ImuPublisher(SensorManager manager)
193 | {
194 | this.sensorManager = manager;
195 | }
196 |
197 | public GraphName getDefaultNodeName()
198 | {
199 | return GraphName.of("android_sensors_driver/imuPublisher");
200 | }
201 |
202 | public void onError(Node node, Throwable throwable)
203 | {
204 | }
205 |
206 | public void onStart(ConnectedNode node)
207 | {
208 | try
209 | {
210 | this.publisher = node.newPublisher("android/imu", "sensor_msgs/Imu");
211 | // Determine if we have the various needed sensors
212 | boolean hasAccel = false;
213 | boolean hasGyro = false;
214 | boolean hasQuat = false;
215 |
216 | List accelList = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
217 |
218 | if(accelList.size() > 0)
219 | {
220 | hasAccel = true;
221 | }
222 |
223 | List gyroList = this.sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
224 | if(gyroList.size() > 0)
225 | {
226 | hasGyro = true;
227 | }
228 |
229 | List quatList = this.sensorManager.getSensorList(Sensor.TYPE_ROTATION_VECTOR);
230 | if(quatList.size() > 0)
231 | {
232 | hasQuat = true;
233 | }
234 |
235 | this.sensorListener = new SensorListener(publisher, hasAccel, hasGyro, hasQuat);
236 | this.imuThread = new ImuThread(this.sensorManager, sensorListener);
237 | this.imuThread.start();
238 | }
239 | catch (Exception e)
240 | {
241 | if (node != null)
242 | {
243 | node.getLog().fatal(e);
244 | }
245 | else
246 | {
247 | e.printStackTrace();
248 | }
249 | }
250 | }
251 |
252 | //@Override
253 | public void onShutdown(Node arg0)
254 | {
255 | this.imuThread.shutdown();
256 |
257 | try
258 | {
259 | this.imuThread.join();
260 | }
261 | catch (InterruptedException e)
262 | {
263 | e.printStackTrace();
264 | }
265 | }
266 |
267 | //@Override
268 | public void onShutdownComplete(Node arg0)
269 | {
270 | }
271 |
272 | }
273 |
274 |
--------------------------------------------------------------------------------
/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.content.Context;
20 | import android.hardware.SensorManager;
21 | import android.location.LocationManager;
22 | import android.os.Bundle;
23 | import android.util.Log;
24 | import android.view.Menu;
25 | import android.view.MenuItem;
26 | import android.view.SubMenu;
27 | import android.view.Window;
28 | import android.view.WindowManager;
29 | import org.ros.address.InetAddressFactory;
30 | import org.ros.android.RosActivity;
31 | import org.ros.node.NodeConfiguration;
32 | import org.ros.node.NodeMainExecutor;
33 |
34 | /**
35 | * @author chadrockey@gmail.com (Chad Rockey)
36 | * @author axelfurlan@gmail.com (Axel Furlan)
37 | */
38 |
39 |
40 | public class MainActivity extends RosActivity
41 | {
42 |
43 |
44 | private NavSatFixPublisher fix_pub;
45 | private ImuPublisher imu_pub;
46 |
47 | private LocationManager mLocationManager;
48 | private SensorManager mSensorManager;
49 |
50 |
51 | public MainActivity()
52 | {
53 | super("Ros Android Sensors Driver", "Ros Android Sensors Driver");
54 | }
55 |
56 | @Override
57 | protected void onPause()
58 | {
59 | super.onPause();
60 | }
61 |
62 | @Override
63 | protected void onCreate(Bundle savedInstanceState)
64 | {
65 | super.onCreate(savedInstanceState);
66 | //requestWindowFeature(Window.FEATURE_NO_TITLE);
67 | //getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
68 | setContentView(R.layout.main);
69 |
70 | mLocationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
71 | mSensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
72 | }
73 |
74 | @Override
75 | protected void onResume()
76 | {
77 | super.onResume();
78 | }
79 |
80 | @Override
81 | public boolean onCreateOptionsMenu(Menu menu) {
82 |
83 | /*SubMenu subPreview = menu.addSubMenu("Color settings");
84 | subPreview.add(1,VIEW_MODE_RGBA,0,"RGB Color").setChecked(true);
85 | subPreview.add(1,VIEW_MODE_GRAY,0,"Grayscale");
86 | subPreview.add(1,VIEW_MODE_CANNY,0,"Canny edges");
87 | subPreview.setGroupCheckable(1, true, true);
88 |
89 | SubMenu subCompression = menu.addSubMenu("Compression");
90 | // subCompression.add(2,IMAGE_TRANSPORT_COMPRESSION_NONE,0,"None");
91 | subCompression.add(2,IMAGE_TRANSPORT_COMPRESSION_PNG,0,"Png");
92 |
93 | SubMenu subCompressionRate = subCompression.addSubMenu(2,IMAGE_TRANSPORT_COMPRESSION_JPEG,0,"Jpeg");
94 | subCompression.setGroupCheckable(2, true, true);
95 | subCompressionRate.setHeaderTitle("Compression quality");
96 | subCompressionRate.getItem().setChecked(true);
97 | subCompressionRate.add(3,50,0,"50");
98 | subCompressionRate.add(3,60,0,"60");
99 | subCompressionRate.add(3,70,0,"70");
100 | subCompressionRate.add(3,80,0,"80").setChecked(true);
101 | subCompressionRate.add(3,90,0,"90");
102 | subCompressionRate.add(3,100,0,"100");
103 | subCompressionRate.setGroupCheckable(3, true, true);*/
104 |
105 | return true;
106 | }
107 |
108 | @Override
109 | public boolean onOptionsItemSelected(MenuItem item)
110 | {
111 | /*if(item.getGroupId() == 1)
112 | {
113 | viewMode = item.getItemId();
114 | item.setChecked(true);
115 | }
116 |
117 | if(item.getGroupId() == 2)
118 | {
119 | imageCompression = item.getItemId();
120 | item.setChecked(true);
121 | }
122 |
123 | if(item.getGroupId() == 3)
124 | {
125 | imageCompressionQuality = item.getItemId();
126 | item.setChecked(true);
127 | }*/
128 | return true;
129 | }
130 |
131 | @Override
132 | protected void init(NodeMainExecutor nodeMainExecutor)
133 | {
134 | NodeConfiguration nodeConfiguration2 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress());
135 | nodeConfiguration2.setMasterUri(getMasterUri());
136 | nodeConfiguration2.setNodeName("android_sensors_driver_nav_sat_fix");
137 | this.fix_pub = new NavSatFixPublisher(mLocationManager);
138 | nodeMainExecutor.execute(this.fix_pub, nodeConfiguration2);
139 |
140 | NodeConfiguration nodeConfiguration3 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress());
141 | nodeConfiguration3.setMasterUri(getMasterUri());
142 | nodeConfiguration3.setNodeName("android_sensors_driver_imu");
143 | this.imu_pub = new ImuPublisher(mSensorManager);
144 | nodeMainExecutor.execute(this.imu_pub, nodeConfiguration3);
145 |
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/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 | this.navSatThread.shutdown();
170 | try {
171 | this.navSatThread.join();
172 | } catch (InterruptedException e) {
173 | e.printStackTrace();
174 | }
175 | }
176 |
177 | //@Override
178 | public void onShutdownComplete(Node arg0) {
179 | }
180 |
181 | public GraphName getDefaultNodeName()
182 | {
183 | return GraphName.of("android_sensors_driver/imuPublisher");
184 | }
185 |
186 | public void onError(Node node, Throwable throwable)
187 | {
188 | }
189 |
190 | }
191 |
--------------------------------------------------------------------------------