I will explain the tutorial application that performs Pub-Sub communication of ROS (Robot Operating System) on Android. The Android ROS app is developed with rosjava, but I created an article because the amount of information in Japanese is less or older than roscpp and rospy.
Basically, I refer to the tutorial http://wiki.ros.org/android on ROS.org.
--General knowledge of Android application development --General knowledge of ROS development
Here, assuming that ROS Master is running on the ROS PC, check the operation of subscribing the published message on the smartphone on the ROS PC (+ smartphone itself).
-** App development PC ** Used for Android application development. - Windows 7 Professional - Android Studio 3.2.1
Detailed procedures for each item are introduced on other sites, so I will omit them.
-** App development PC ** It seems that it was necessary to build a ROS environment on the application development PC before, but now it can be developed only with Android Studio. --Install Android Studio --Install the Nexus 5X USB driver --Install API 15 or above SDK
-** Network ** Connect your smartphone and ROS PC to the same network. In my environment, the IP address is as follows. --Smartphone: 192.168.0.14 - ROS PC:192.168.0.15
-** Create an app with New-> New Project in Android Studio ** --Select API 15 or later for "Target Android Devices" in "Phone and Tablet" -Select "Empty Activity" for "Add an Activity to Mobile" --Other than that, it is OK by default
-** Edit build.gradle (Top level) **
build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
buildscript {
apply from: "https://github.com/rosjava/android_core/raw/kinetic/buildscript.gradle"
}
subprojects {
apply plugin: 'ros-android'
afterEvaluate { project ->
android {
// Exclude a few files that are duplicated across our dependencies and
// prevent packaging Android applications.
packagingOptions {
exclude "META-INF/LICENSE.txt"
exclude "META-INF/NOTICE.txt"
}
}
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Here, in the original tutorial
Edit the top-level build.gradle file and replace this part:
with this:
There is a statement (I added the emphasis on replace), but in my environment I got an error when I deleted the first buildscript, so I left it as it is.
-** Edit build.gradle (app) **
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "goodclues.example.myrosapplication"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'org.ros.android_core:android_15:[0.3,0.4)'
}
The last "implementation" is "compile" at home, but it seems to be deprecated now. ~~ Also, let's change the number 15 of "android_15" according to the API level. ~~ (← Please point out in the comments, it seems that the numbers and API level are not related. Also, it seems that the description method has changed now, so please check the tutorial for the latest information.)
-** Add permissions to AndroidManifest.xml **
<uses-permission android:name="android.permission.INTERNET" />
Permission to use the network.
-** Add activity to AndroidManifest.xml **
<activity android:name="org.ros.android.MasterChooser" />
Master Chooser is an activity to specify the URI of ROS Master. If you describe this, the setting screen will be displayed automatically when the application is started. You can also hard-code the Master URI, but see the original tutorial for how to do this.
-** Add the following to AndroidManifest.xml **
<application xmlns:tools="http://schemas.android.com/tools"
tools:replace="android:icon"
...(Continued below)
I'm not sure why, but without it I'm getting an error. The final manifest file looks like this:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="goodclues.example.myrosapplication">
<uses-permission android:name="android.permission.INTERNET" />
<application xmlns:tools="http://schemas.android.com/tools"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:icon">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="org.ros.android.MasterChooser" />
</application>
-** Change the text of activity_main.xml ** --Changed the default TextView view to org.ros.android.view.RosTextView --Added id = "@ + id / text"
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<org.ros.android.view.RosTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
-** Edit MainActivity **
To use ROS, create an Activity that extends RosActivity. The sample below has a class called Talker that publishes a / chatter message and a view that subscribes to a chatter topic called RosTextView.
The Talker class internally publishes a number that is incremented every second.
MainActivity.java
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package goodclues.example.myrosapplication;
import android.os.Bundle;
import org.ros.android.MessageCallable;
import org.ros.android.RosActivity;
import org.ros.android.view.RosTextView;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeMainExecutor;
/**
* @author [email protected] (Damon Kohler)
*/
public class MainActivity extends RosActivity {
private RosTextView<std_msgs.String> rosTextView;
private Talker talker;
public MainActivity() {
// The RosActivity constructor configures the notification title and ticker
// messages.
super("Pubsub Tutorial", "Pubsub Tutorial");
}
@SuppressWarnings("unchecked")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rosTextView = (RosTextView<std_msgs.String>) findViewById(R.id.text);
rosTextView.setTopicName("chatter");
rosTextView.setMessageType(std_msgs.String._TYPE);
rosTextView.setMessageToStringCallable(new MessageCallable<String, std_msgs.String>() {
@Override
public String call(std_msgs.String message) {
return message.getData();
}
});
}
@Override
protected void init(NodeMainExecutor nodeMainExecutor) {
talker = new Talker();
// At this point, the user has already been prompted to either enter the URI
// of a master to use or to start a master locally.
// The user can easily use the selected ROS Hostname in the master chooser
// activity.
NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(getRosHostname());
nodeConfiguration.setMasterUri(getMasterUri());
nodeMainExecutor.execute(talker, nodeConfiguration);
// The RosTextView is also a NodeMain that must be executed in order to
// start displaying incoming messages.
nodeMainExecutor.execute(rosTextView, nodeConfiguration);
}
}
I borrow the sample almost as it is. However, at the head family
import org.ros.rosjava_tutorial_pubsub.Talker;
However, since an error occurred in my environment, I copied the following source and created a Talker class in my project. http://docs.ros.org/hydro/api/rosjava_core/html/Talker_8java_source.html
Start roscore on your ROS PC.
$ roscore
Next, when you start the app, the following ROS Master connection setting screen will be displayed. (If you check Show advanced options, you will see a button to make detailed network settings and the smartphone itself a ROS Master, but I will omit it here because it is unnecessary)
Enter the URI of the ROS Master in "Master URI". It is OK if you change the place where it is "localhost" to "192.168.0.15" set above. Next, tap CONNECT and if the connection is successful, it will transition to Main Activity.
The number displayed to the right of Hello world! Is the message you are subscribing to (published by yourself).
Now, let's check if you can subscribe on ROS PC. At the terminal
$ rostopic echo /chatter
Then
data: "Hello world! X"
If the message is output at regular intervals like this, it is successful. (X is a number)
I explained the procedure of Android application development that realizes simple Pub-Sub communication along with the tutorial of ROS.org. This will make it easier to link the robot with a smartphone camera, etc., so please give it a try.
Recommended Posts