├── pepper-gamepad-root
├── settings.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── sample-app
│ ├── src
│ │ └── main
│ │ │ ├── assets
│ │ │ └── robot
│ │ │ │ └── robotsdk.xml
│ │ │ ├── res
│ │ │ ├── drawable
│ │ │ │ ├── error.png
│ │ │ │ ├── background.gif
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── drawable-fr-rFR
│ │ │ │ ├── error.png
│ │ │ │ └── background.gif
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values-fr
│ │ │ │ └── strings.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ └── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── softbankrobotics
│ │ │ └── peppergamepadsample
│ │ │ └── MainActivity.kt
│ ├── libs
│ │ └── remotecontrollibrary-0.0.3.aar
│ ├── proguard-rules.pro
│ └── build.gradle
├── pepper-gamepad
│ ├── src
│ │ └── main
│ │ │ ├── assets
│ │ │ └── robot
│ │ │ │ └── robotsdk.xml
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── softbankrobotics
│ │ │ └── peppergamepad
│ │ │ └── RemoteRobotController.kt
│ ├── compiled
│ │ └── pepper-gamepad-1.0.0.aar
│ ├── proguard-rules.pro
│ └── build.gradle
├── build.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
├── AUTHORS.md
├── .gitignore
├── COPYING.md
└── README.md
/pepper-gamepad-root/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':pepper-gamepad', ':sample-app'
2 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/assets/robot/robotsdk.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/pepper-gamepad/src/main/assets/robot/robotsdk.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/drawable/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/drawable/error.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/pepper-gamepad/compiled/pepper-gamepad-1.0.0.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/pepper-gamepad/compiled/pepper-gamepad-1.0.0.aar
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/libs/remotecontrollibrary-0.0.3.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/libs/remotecontrollibrary-0.0.3.aar
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/drawable/background.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/drawable/background.gif
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/drawable-fr-rFR/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/drawable-fr-rFR/error.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/drawable-fr-rFR/background.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/drawable-fr-rFR/background.gif
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softbankrobotics-labs/pepper-gamepad/HEAD/pepper-gamepad-root/sample-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jul 31 11:48:58 CEST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
7 |
--------------------------------------------------------------------------------
/AUTHORS.md:
--------------------------------------------------------------------------------
1 | ## Pepper Gamepad Authors
2 |
3 | The Pepper Gamepad library was written by the Developer Experience team at Softbank Robotics, Paris, July 2019.
4 |
5 | * **Alexandre Roux** (aroux@softbankrobotics.com )
6 | * **Joss Stuart** (joss.stuart@softbankrobotics.com)
7 | * **Émile Kroeger** (ekroeger@softbankrobotics.com)
8 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/pepper-gamepad/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
18 | # Windows thumbnail db
19 | Thumbs.db
20 |
21 | # OSX files
22 | .DS_Store
23 |
24 | # Android Studio
25 | *.iml
26 | .idea
27 | .gradle
28 | build/
29 | .navigation
30 | captures/
31 | output.json
32 |
33 | # NDK
34 | obj/
35 | .externalNativeBuild
36 |
37 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/pepper-gamepad/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.61'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.6.1'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | maven { url 'https://qisdk.softbankrobotics.com/sdk/maven' }
23 | maven { url 'https://jitpack.io' }
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 | android.useAndroidX=true
17 | android.enableJetifier=true
18 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Pepper Gamepad Sample
3 |
4 | - Great, let\'s have fun together! Take the game pad, look at the controls and we\'re good to go!
5 | - Time to put these wheels to good use! I hope you have a game pad ready, take a look at the controls and let\'s go!
6 | - Can\'t wait to see where you\'ll take me! Here\'s how to use your game pad, take a look and let\'s go for a ride!
7 |
8 |
9 | - Oopsie, the gamepad is not connected. Please look at my tablet to see how to do it!
10 | - Looks like no gamepad is connected, take a look at my tablet to see how to remedy this!
11 | - I can\'t detect the gamepad, please look at my tablet to see how to connect it!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Pepper Gamepad Sample
4 |
5 | - Génial, on part en balade! Prends ta manette, jette un oeil aux contrôles et on y va!
6 | - Super, j\'avais hâte de me dégourdir les roues! J\'espère que tu as ta manette, je t\'affiche un petit rappel des contrôles avant d\'y aller.
7 | - J\'ai hâte de voir où tu vas m\'en mné! Prépare ta manette, jette un oeil aux contrôles et c\'est parti!
8 |
9 |
10 | - Oupsse, la manette n\'est pas connectée. Regarde sur ma tablette pour voir comment faire!
11 | - Ah mince, je ne détecte pas la manette. Regarde sur ma tablette pour voir comment la connecter!
12 | - Ah, on dirait que la manette n\'est pas connectée, j\'affiche les instructions pour le faire sur ma tablette!
13 |
14 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/pepper-gamepad/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | android {
6 | archivesBaseName = "pepper-gamepad"
7 | version = "1.0.3"
8 | compileSdkVersion 29
9 | defaultConfig {
10 | minSdkVersion 23
11 | targetSdkVersion 29
12 | versionCode 4
13 | versionName "1.0.3"
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | compileOptions {
23 | sourceCompatibility = 1.8
24 | targetCompatibility = 1.8
25 | }
26 | libraryVariants.all { variant ->
27 | variant.outputs.all { output ->
28 | outputFileName = "${archivesBaseName}-${version}.aar"
29 | }
30 | }
31 | }
32 |
33 | dependencies {
34 | implementation fileTree(dir: 'libs', include: ['*.jar'])
35 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
36 |
37 | implementation 'com.aldebaran:qisdk:1.6.7'
38 | implementation 'com.aldebaran:qisdk-design:1.6.7'
39 | }
40 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 29
9 | defaultConfig {
10 | applicationId "com.softbankrobotics.peppergamepadsample"
11 | minSdkVersion 23
12 | targetSdkVersion 29
13 | versionCode 2
14 | versionName "1.1.0"
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | compileOptions {
24 | sourceCompatibility = 1.8
25 | targetCompatibility = 1.8
26 | }
27 | }
28 |
29 | dependencies {
30 | implementation fileTree(dir: 'libs', include: ['*.jar'])
31 |
32 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
33 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
34 |
35 | implementation 'com.aldebaran:qisdk:1.6.7'
36 | implementation 'com.aldebaran:qisdk-design:1.6.7'
37 |
38 | implementation project(":pepper-gamepad")
39 |
40 | implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'
41 | }
42 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
30 |
31 |
--------------------------------------------------------------------------------
/COPYING.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-2019, SoftBank Robotics
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the SoftBank Robotics nor the
12 | names of its contributors may be used to endorse or promote products
13 | derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL SoftBank Robotics BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Pepper Gamepad Remote Control Library
2 |
3 | This Android Library will help you to connect an external controller and map buttons in order to make a Pepper move, using the QiSDK.
4 |
5 | This library was tested with a Xbox One Controller, but can be used with any Bluetooth input device.
6 |
7 | ### Video Demonstration
8 |
9 | This video was filmed at SoftBank Robotics Europe, and shows the basic control scheme while navigating around the SBRE Showroom.
10 |
11 | [Watch video on YouTube](https://youtu.be/ECXIhBUcHZ8)
12 |
13 | ## Getting Started
14 |
15 | ### Prerequisites
16 |
17 | A robotified project for Pepper with QiSDK. Read the [documentation](https://developer.softbankrobotics.com/pepper-qisdk) if needed
18 |
19 | A connection to an external controller.
20 |
21 | ### Connecting a Controller
22 |
23 | 1. Turn on the Bluetooth for the Android Tablet on Pepper.
24 | 2. Set you controller to pairing mode. This will differ between devices, please check the instructions for your specific device if unsure.
25 | 3. In the Tablet settings, navigate to Bluetooth Settings, find the device and pair it.
26 |
27 | ### Running the Sample Application
28 |
29 | The project comes complete with a sample project. You can clone the repository, open it in Android Studio, and run this directly onto a Robot.
30 |
31 | The sample application will handle the case where the controller is not connected, you can use a similar function in your own application.
32 |
33 | Because any number of external controllers can be used, and the mapping needed may be different, it is necessary to override `onGenericMotionEvent` and pass the values to the `RemoteRobotController` in the **pepper-gamepad** library.
34 |
35 | Full implementation details are available to see in the sample project.
36 |
37 | ### Installing
38 |
39 | [**Follow these instructions**](https://jitpack.io/#softbankrobotics-labs/pepper-gamepad)
40 |
41 | Make sure to replace 'Tag' by the number of the version of the library you want to use.
42 |
43 | ## Usage
44 |
45 | *This README assumes some standard setup can be done by the user, such as initialising variables or implementing code in the correct functions. Refer to the Sample Project for full usage code.*
46 |
47 | Initialise the QISDK in the onCreate. If you are unsure how to do this, refer to the [QISDK tutorials](https://developer.softbankrobotics.com/pepper-qisdk/getting-started/creating-robot-application)
48 |
49 | QiSDK.register(this, this)
50 |
51 | In the `onRobotFocusGained`, disable BasicAwareness, and instantiate a `RemoteRobotController` object by passing it the QiContext. Then start it.
52 |
53 | ```
54 | override fun onRobotFocusGained(qiContext: QiContext) {
55 | val basicAwarenessHolder = HolderBuilder.with(qiContext)
56 | .withAutonomousAbilities(AutonomousAbilitiesType.BASIC_AWARENESS)
57 | .build()
58 |
59 | basicAwarenessHolder.async().hold().thenConsume {
60 | when {
61 | it.isSuccess -> Log.i(TAG, "BasicAwareness held with success")
62 | it.hasError() -> Log.e(TAG, "holdBasicAwareness error: " + it.errorMessage)
63 | it.isCancelled -> Log.e(TAG, "holdBasicAwareness cancelled")
64 | }
65 | }
66 |
67 | remoteRobotController = RemoteRobotController(qiContext)
68 | remoteRobotController.start()
69 | }
70 | ```
71 | Get the position of the controller and call updateTarget method. It is important to call this function in a thread, as it is using references to the QISDK.
72 | ```
73 | remoteRobotController.updateTarget(leftJoystickX, leftJoystickY, rightJoystickX, rightJoystickY)
74 | ```
75 | - Left joystick makes Pepper translate
76 | - Right joystick makes Pepper rotate
77 |
78 | Example :
79 |
80 | ```
81 | override fun onGenericMotionEvent(event: MotionEvent): Boolean {
82 |
83 | // Add null protection for when the controller disconnects
84 | val inputDevice = event.device ?: return super.onGenericMotionEvent(event)
85 |
86 | // Get left joystick coordinates
87 | val leftJoystickX = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X)
88 | val leftJoystickY = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y)
89 |
90 | // Get right joystick coordinates
91 | val rightJoystickX = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z)
92 | val rightJoystickY = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ)
93 |
94 | if (::remoteRobotController.isInitialized) {
95 | thread {
96 | remoteRobotController.updateTarget(leftJoystickX, leftJoystickY, rightJoystickX, rightJoystickY)
97 | }
98 | }
99 |
100 | return true
101 | }
102 |
103 | private fun getCenteredAxis(event: MotionEvent, device: InputDevice, axis: Int): Float {
104 | val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source)
105 |
106 | // A joystick at rest does not always report an absolute position of
107 | // (0,0). Use the getFlat() method to determine the range of values bounding the joystick axis center.
108 |
109 | range?.apply {
110 | val value = event.getAxisValue(axis)
111 |
112 | // Ignore axis values that are within the 'flat' region of the joystick axis center.
113 | if (Math.abs(value) > flat) {
114 | return value
115 | }
116 | }
117 |
118 | return 0f
119 | }
120 | ```
121 |
122 | You can stop `RemoteRobotController` object whenever you want by calling the `stop()` method. This can be helpfull if you want to run animations for instance:
123 |
124 | ```
125 | remoteRobotController.stop()
126 | myCustomAnimation.run()
127 | remoteRobotController.start()
128 | ```
129 |
130 | ## License
131 |
132 | This project is licensed under the BSD 3-Clause "New" or "Revised" License- see the [COPYING](COPYING.md) file for details
133 |
134 |
135 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/pepper-gamepad/src/main/java/com/softbankrobotics/peppergamepad/RemoteRobotController.kt:
--------------------------------------------------------------------------------
1 | package com.softbankrobotics.peppergamepad
2 |
3 | import android.util.Log
4 | import com.aldebaran.qi.Future
5 | import com.aldebaran.qi.sdk.QiContext
6 | import com.aldebaran.qi.sdk.`object`.actuation.AttachedFrame
7 | import com.aldebaran.qi.sdk.`object`.actuation.LookAt
8 | import com.aldebaran.qi.sdk.`object`.actuation.LookAtMovementPolicy
9 | import com.aldebaran.qi.sdk.`object`.geometry.Transform
10 | import com.aldebaran.qi.sdk.builder.AnimateBuilder
11 | import com.aldebaran.qi.sdk.builder.AnimationBuilder
12 | import com.aldebaran.qi.sdk.builder.LookAtBuilder
13 | import com.aldebaran.qi.sdk.builder.TransformBuilder
14 | import kotlin.math.atan2
15 | import kotlin.math.cos
16 | import kotlin.math.roundToInt
17 | import kotlin.math.sin
18 |
19 | class RemoteRobotController(private val qiContext: QiContext) {
20 |
21 | private val TAG = "RemoteRobotController"
22 |
23 | var isRunning = false
24 | private set
25 | private var startAfterInitialization = false
26 | private var isMoving = false
27 |
28 | private var currentLeftJoystickX = 0
29 | private var currentLeftJoystickY = 0
30 | private var currentRightJoystickX = 0
31 | private var currentRightJoystickY = 0
32 |
33 | private lateinit var lookAtFuture: Future
34 | private lateinit var animateFuture: Future
35 |
36 | private lateinit var defaultPosition: Transform
37 | private lateinit var targetFrame: AttachedFrame
38 | private lateinit var lookAt: LookAt
39 |
40 | init {
41 | qiContext.actuation.async().gazeFrame().andThenConsume { robotFrame ->
42 | defaultPosition = TransformBuilder.create().fromXTranslation(100.0)
43 | targetFrame = robotFrame.makeAttachedFrame(defaultPosition)
44 | lookAt = LookAtBuilder.with(qiContext).withFrame(targetFrame.frame()).build()
45 | lookAt.addOnStartedListener {
46 | Log.i(TAG, "LookAt started")
47 | }
48 | if (startAfterInitialization) start()
49 | }
50 | }
51 |
52 | fun start() {
53 | Log.d(TAG, "start")
54 |
55 | if (!::lookAt.isInitialized) {
56 | startAfterInitialization = true
57 | return
58 | }
59 |
60 | if (isRunning) return
61 |
62 | lookAtFuture = lookAt.async().run()
63 | lookAtFuture.thenConsume {
64 | when {
65 | lookAtFuture.isDone -> Log.i(TAG, "LookAt done")
66 | lookAtFuture.hasError() -> Log.e(TAG, "LookAt error: ${lookAtFuture.errorMessage}")
67 | lookAtFuture.isCancelled -> Log.e(TAG, "LookAt cancelled")
68 | }
69 | }
70 |
71 | isRunning = true
72 | }
73 |
74 | fun stop() {
75 | Log.d(TAG, "stop")
76 |
77 | if (!isRunning) return
78 |
79 | lookAtFuture.requestCancellation()
80 | animateFuture.requestCancellation()
81 |
82 | isRunning = false
83 | }
84 |
85 | fun updateTarget(
86 | newLeftJoystickX: Float,
87 | newLeftJoystickY: Float,
88 | newRightJoystickX: Float,
89 | newRightJoystickY: Float
90 | ) {
91 | Log.d(
92 | TAG, "updateTarget newLeftJoystickX=$newLeftJoystickX " +
93 | "newLeftJoystickY=$newLeftJoystickY " +
94 | "newRightJoystickX=$newRightJoystickX " +
95 | "newRightJoystickY=$newRightJoystickY"
96 | )
97 |
98 | // Round values
99 | var roundedNewLeftJoystickX = 0
100 | var roundedNewLeftJoystickY = 0
101 | if (!(newLeftJoystickX == 0f && newLeftJoystickY == 0f)) {
102 | val leftJoystickTheta = atan2(newLeftJoystickY, newLeftJoystickX)
103 | roundedNewLeftJoystickX = (cos(leftJoystickTheta) * 2).roundToInt() * 5
104 | roundedNewLeftJoystickY = (sin(leftJoystickTheta) * 2).roundToInt() * 5
105 | }
106 | var roundedNewRightJoystickX = 0
107 | var roundedNewRightJoystickY = 0
108 | if (!(newRightJoystickX == 0f && newRightJoystickY == 0f)) {
109 | val rightJoystickTheta = atan2(newRightJoystickY, newRightJoystickX)
110 | roundedNewRightJoystickX = (cos(rightJoystickTheta) * 10).roundToInt()
111 | roundedNewRightJoystickY = (sin(rightJoystickTheta) * 10).roundToInt()
112 | }
113 |
114 | // Avoid repeating commands
115 | if (!(roundedNewLeftJoystickX == currentLeftJoystickX && roundedNewLeftJoystickY == currentLeftJoystickY)) {
116 | currentLeftJoystickX = roundedNewLeftJoystickX
117 | currentLeftJoystickY = roundedNewLeftJoystickY
118 |
119 | makeTranslation()
120 | }
121 | if (!(roundedNewRightJoystickX == currentRightJoystickX && roundedNewRightJoystickY == currentRightJoystickY)) {
122 | currentRightJoystickX = roundedNewRightJoystickX
123 | currentRightJoystickY = roundedNewRightJoystickY
124 |
125 | makeRotation()
126 | }
127 | }
128 |
129 | private fun makeTranslation() {
130 | Log.d(
131 | TAG,
132 | "makeTranslation currentLeftJoystickX=$currentLeftJoystickX currentLeftJoystickY=$currentLeftJoystickY"
133 | )
134 |
135 | if (!isRunning) return
136 |
137 | if (::animateFuture.isInitialized && !animateFuture.isDone) {
138 | animateFuture.requestCancellation()
139 | } else if (!(currentLeftJoystickX == 0 && currentLeftJoystickY == 0) && !isMoving) {
140 | isMoving = true
141 | lookAt.async().setPolicy(LookAtMovementPolicy.HEAD_ONLY).andThenConsume {
142 | val targetX = -currentLeftJoystickY.toDouble()
143 | val targetY = -currentLeftJoystickX.toDouble()
144 |
145 | val animationString = "[\"Holonomic\", [\"Line\", [$targetX, $targetY]], 0.0, 40.0]"
146 | val animation = AnimationBuilder.with(qiContext).withTexts(animationString).build()
147 | val animate = AnimateBuilder.with(qiContext).withAnimation(animation).build()
148 | animate.addOnStartedListener {
149 | Log.i(TAG, "Animate started")
150 |
151 | if (!(targetX == -currentLeftJoystickY.toDouble() && targetY == -currentLeftJoystickX.toDouble())) {
152 | animateFuture.requestCancellation()
153 | }
154 | }
155 |
156 | animateFuture = animate.async().run()
157 | animateFuture.thenConsume {
158 | when {
159 | animateFuture.isSuccess -> Log.i(TAG, "Animate finished with success")
160 | animateFuture.hasError() -> Log.e(
161 | TAG,
162 | "Animate error: ${animateFuture.errorMessage}"
163 | )
164 | animateFuture.isCancelled -> Log.i(TAG, "Animate cancelled")
165 | }
166 |
167 | lookAt.policy = LookAtMovementPolicy.HEAD_AND_BASE
168 | isMoving = false
169 |
170 | makeTranslation()
171 | }
172 | }
173 | }
174 | }
175 |
176 | private fun makeRotation() {
177 | Log.d(
178 | TAG,
179 | "makeRotation currentRightJoystickX=$currentRightJoystickX currentRightJoystickY=$currentRightJoystickY"
180 | )
181 |
182 | if (!isRunning) return
183 |
184 | if (currentRightJoystickX == 0 && currentRightJoystickY == 0) {
185 | targetFrame.update(defaultPosition)
186 | } else {
187 | val targetX = -currentRightJoystickY.toDouble()
188 | val targetY = -currentRightJoystickX.toDouble()
189 |
190 | val transform = TransformBuilder.create().from2DTranslation(targetX, targetY)
191 | targetFrame.update(transform)
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/pepper-gamepad-root/sample-app/src/main/java/com/softbankrobotics/peppergamepadsample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.softbankrobotics.peppergamepadsample
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.hardware.input.InputManager
6 | import android.hardware.input.InputManager.InputDeviceListener
7 | import android.os.Bundle
8 | import android.util.Log
9 | import android.view.InputDevice
10 | import android.view.MotionEvent
11 | import android.view.View
12 | import com.aldebaran.qi.sdk.QiContext
13 | import com.aldebaran.qi.sdk.QiSDK
14 | import com.aldebaran.qi.sdk.RobotLifecycleCallbacks
15 | import com.aldebaran.qi.sdk.`object`.holder.AutonomousAbilitiesType
16 | import com.aldebaran.qi.sdk.`object`.holder.Holder
17 | import com.aldebaran.qi.sdk.builder.HolderBuilder
18 | import com.aldebaran.qi.sdk.builder.SayBuilder
19 | import com.softbankrobotics.peppergamepad.RemoteRobotController
20 | import kotlinx.android.synthetic.main.activity_main.*
21 | import kotlin.concurrent.thread
22 | import kotlin.math.abs
23 | import kotlin.random.Random
24 |
25 | class MainActivity : Activity(), RobotLifecycleCallbacks, InputDeviceListener {
26 |
27 | companion object {
28 | private const val TAG = "RemoteControlSample"
29 | }
30 |
31 | private lateinit var inputManager: InputManager
32 |
33 | private var qiContext: QiContext? = null
34 | private lateinit var basicAwarenessHolder: Holder
35 |
36 | private lateinit var remoteRobotController: RemoteRobotController
37 |
38 | override fun onCreate(savedInstanceState: Bundle?) {
39 | super.onCreate(savedInstanceState)
40 |
41 | setContentView(R.layout.activity_main)
42 |
43 | QiSDK.register(this, this)
44 |
45 | inputManager = getSystemService(Context.INPUT_SERVICE) as InputManager
46 | }
47 |
48 | override fun onResume() {
49 | super.onResume()
50 | inputManager.registerInputDeviceListener(this, null)
51 | checkControllerConnection()
52 |
53 | // Enables sticky immersive mode.
54 | window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
55 | // Set the content to appear under the system bars so that the
56 | // content doesn't resize when the system bars hide and show.
57 | or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
58 | or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
59 | or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
60 | // Hide the nav bar and status bar
61 | or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
62 | or View.SYSTEM_UI_FLAG_FULLSCREEN)
63 | }
64 |
65 | override fun onInputDeviceRemoved(deviceId: Int) {
66 | Log.d(TAG, "onInputDeviceRemoved")
67 | checkControllerConnection()
68 | }
69 |
70 | override fun onInputDeviceAdded(deviceId: Int) {
71 | Log.d(TAG, "onInputDeviceAdded")
72 | checkControllerConnection()
73 | }
74 |
75 | override fun onInputDeviceChanged(deviceId: Int) {
76 | Log.d(TAG, "onInputDeviceChanged")
77 | checkControllerConnection()
78 | }
79 |
80 | private fun checkControllerConnection() {
81 | val connectedControllers = getGameControllerIds()
82 | if (connectedControllers.isEmpty()) {
83 | runOnUiThread {
84 | backgroundGifImageView.visibility = View.INVISIBLE
85 | errorImageView.visibility = View.VISIBLE
86 | }
87 |
88 | val errorSentences = resources.getStringArray(R.array.error)
89 | sayRandomSentence(errorSentences)
90 | } else {
91 | runOnUiThread {
92 | backgroundGifImageView.visibility = View.VISIBLE
93 | errorImageView.visibility = View.INVISIBLE
94 | }
95 |
96 | val welcomeSentences = resources.getStringArray(R.array.welcome)
97 | sayRandomSentence(welcomeSentences)
98 | }
99 | }
100 |
101 | private fun sayRandomSentence(sentencesArray: Array) {
102 | if (qiContext == null) {
103 | return
104 | }
105 |
106 | val i = Random.nextInt(0, sentencesArray.size - 1)
107 | SayBuilder.with(qiContext)
108 | .withText(sentencesArray[i])
109 | .buildAsync().andThenConsume {
110 | it.async().run()
111 | }
112 | }
113 |
114 | private fun getGameControllerIds(): List {
115 | val gameControllerDeviceIds = mutableListOf()
116 | val deviceIds = inputManager.inputDeviceIds
117 | deviceIds.forEach { deviceId ->
118 | InputDevice.getDevice(deviceId).apply {
119 |
120 | // Verify that the device has gamepad buttons, control sticks, or both.
121 | if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
122 | || sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
123 | ) {
124 | // This device is a game controller. Store its device ID.
125 | gameControllerDeviceIds
126 | .takeIf { !it.contains(deviceId) }
127 | ?.add(deviceId)
128 | }
129 | }
130 | }
131 | return gameControllerDeviceIds
132 | }
133 |
134 | override fun onRobotFocusGained(qiContext: QiContext) {
135 | Log.i(TAG, "onRobotFocusGained")
136 | this.qiContext = qiContext
137 |
138 | checkControllerConnection()
139 |
140 | // Hold Basic Awareness to avoid robot getting distracted
141 | basicAwarenessHolder = HolderBuilder.with(qiContext)
142 | .withAutonomousAbilities(AutonomousAbilitiesType.BASIC_AWARENESS)
143 | .build()
144 | basicAwarenessHolder.async().hold().thenConsume {
145 | when {
146 | it.isSuccess -> Log.i(TAG, "BasicAwareness held with success")
147 | it.hasError() -> Log.e(TAG, "holdBasicAwareness error: " + it.errorMessage)
148 | it.isCancelled -> Log.e(TAG, "holdBasicAwareness cancelled")
149 | }
150 | }
151 | remoteRobotController = RemoteRobotController(qiContext)
152 | remoteRobotController.start()
153 | }
154 |
155 | override fun onGenericMotionEvent(event: MotionEvent): Boolean {
156 | Log.d(TAG, "onGenericMotionEvent $event")
157 |
158 | // Add null protection for when the controller disconnects
159 | val inputDevice = event.device ?: return super.onGenericMotionEvent(event)
160 |
161 | // Get left joystick coordinates
162 | val leftJoystickX = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X)
163 | val leftJoystickY = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y)
164 |
165 | // Get right joystick coordinates
166 | val rightJoystickX = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z)
167 | val rightJoystickY = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ)
168 |
169 | if (::remoteRobotController.isInitialized) {
170 | thread {
171 | remoteRobotController.updateTarget(
172 | leftJoystickX,
173 | leftJoystickY,
174 | rightJoystickX,
175 | rightJoystickY
176 | )
177 | }
178 | } else {
179 | Log.d(TAG, "@@@@@@@@@ not initialized")
180 | }
181 |
182 | return true
183 | }
184 |
185 | private fun getCenteredAxis(
186 | event: MotionEvent,
187 | device: InputDevice,
188 | axis: Int
189 | ): Float {
190 | val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source)
191 |
192 | // A joystick at rest does not always report an absolute position of
193 | // (0,0). Use the getFlat() method to determine the range of values
194 | // bounding the joystick axis center.
195 | range?.apply {
196 | val value = event.getAxisValue(axis)
197 |
198 | // Ignore axis values that are within the 'flat' region of the
199 | // joystick axis center.
200 | if (abs(value) > flat) {
201 | return value
202 | }
203 | }
204 | return 0f
205 | }
206 |
207 | override fun onRobotFocusLost() {
208 | Log.i(TAG, "onRobotFocusLost")
209 | qiContext = null
210 | remoteRobotController.stop()
211 | }
212 |
213 | override fun onRobotFocusRefused(reason: String?) {
214 | Log.e(TAG, "onRobotFocusRefused: $reason")
215 | }
216 |
217 | override fun onPause() {
218 | super.onPause()
219 | inputManager.unregisterInputDeviceListener(this)
220 | }
221 |
222 | override fun onDestroy() {
223 | super.onDestroy()
224 | QiSDK.unregister(this, this)
225 | }
226 | }
227 |
--------------------------------------------------------------------------------