From 351634c1456ebb6f991b56bb0e378b8e51cf68ba Mon Sep 17 00:00:00 2001 From: Alexandre ROUX Date: Tue, 31 Aug 2021 15:31:41 +0200 Subject: [PATCH] peppergamepad-1.0.4 Add start() and stop() methods Bug fixes Warnings removal Stop RemoteRobotController in onRobotFocusLost() Update README --- README.md | 19 +-- pepper-gamepad-root/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../pepper-gamepad/build.gradle | 4 +- .../peppergamepad/RemoteRobotController.kt | 139 ++++++++++++------ pepper-gamepad-root/sample-app/build.gradle | 4 +- .../peppergamepadsample/MainActivity.kt | 10 +- .../src/main/res/values-fr/strings.xml | 2 - .../src/main/res/values/strings.xml | 2 - 9 files changed, 119 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index a042aaf..c745b32 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ This video was filmed at SoftBank Robotics Europe, and shows the basic control s ## Getting Started - ### Prerequisites A robotified project for Pepper with QiSDK. Read the [documentation](https://developer.softbankrobotics.com/pepper-qisdk) if needed @@ -41,7 +40,6 @@ Full implementation details are available to see in the sample project. Make sure to replace 'Tag' by the number of the version of the library you want to use. - ## Usage *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.* @@ -50,8 +48,7 @@ Initialise the QISDK in the onCreate. If you are unsure how to do this, refer to QiSDK.register(this, this) -In the `onRobotFocusGained`, disable BasicAwareness, and instantiate a `RemoteRobotController` object by passing it the QiContext. - +In the `onRobotFocusGained`, disable BasicAwareness, and instantiate a `RemoteRobotController` object by passing it the QiContext. Then start it. ``` override fun onRobotFocusGained(qiContext: QiContext) { @@ -68,17 +65,13 @@ override fun onRobotFocusGained(qiContext: QiContext) { } remoteRobotController = RemoteRobotController(qiContext) + remoteRobotController.start() } ``` - - - - 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. ``` remoteRobotController.updateTarget(leftJoystickX, leftJoystickY, rightJoystickX, rightJoystickY) ``` - - Left joystick makes Pepper translate - Right joystick makes Pepper rotate @@ -126,6 +119,14 @@ private fun getCenteredAxis(event: MotionEvent, device: InputDevice, axis: Int): } ``` +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: + +``` +remoteRobotController.stop() +myCustomAnimation.run() +remoteRobotController.start() +``` + ## License This project is licensed under the BSD 3-Clause "New" or "Revised" License- see the [COPYING](COPYING.md) file for details diff --git a/pepper-gamepad-root/build.gradle b/pepper-gamepad-root/build.gradle index ae8e1ca..1bf0636 100644 --- a/pepper-gamepad-root/build.gradle +++ b/pepper-gamepad-root/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.41' + ext.kotlin_version = '1.3.61' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.2' + classpath 'com.android.tools.build:gradle:3.6.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.properties b/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.properties index 4fe4b55..4054ae2 100644 --- a/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.properties +++ b/pepper-gamepad-root/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/pepper-gamepad-root/pepper-gamepad/build.gradle b/pepper-gamepad-root/pepper-gamepad/build.gradle index 7261e62..41037c5 100644 --- a/pepper-gamepad-root/pepper-gamepad/build.gradle +++ b/pepper-gamepad-root/pepper-gamepad/build.gradle @@ -5,10 +5,10 @@ apply plugin: 'kotlin-android' android { archivesBaseName = "pepper-gamepad" version = "1.0.3" - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 23 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 4 versionName "1.0.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/pepper-gamepad-root/pepper-gamepad/src/main/java/com/softbankrobotics/peppergamepad/RemoteRobotController.kt b/pepper-gamepad-root/pepper-gamepad/src/main/java/com/softbankrobotics/peppergamepad/RemoteRobotController.kt index b7757de..a38cf2a 100644 --- a/pepper-gamepad-root/pepper-gamepad/src/main/java/com/softbankrobotics/peppergamepad/RemoteRobotController.kt +++ b/pepper-gamepad-root/pepper-gamepad/src/main/java/com/softbankrobotics/peppergamepad/RemoteRobotController.kt @@ -16,12 +16,13 @@ import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin -class RemoteRobotController(context: QiContext) { +class RemoteRobotController(private val qiContext: QiContext) { private val TAG = "RemoteRobotController" - private val qiContext = context - + var isRunning = false + private set + private var startAfterInitialization = false private var isMoving = false private var currentLeftJoystickX = 0 @@ -29,20 +30,35 @@ class RemoteRobotController(context: QiContext) { private var currentRightJoystickX = 0 private var currentRightJoystickY = 0 - private var lookAtFuture: Future + private lateinit var lookAtFuture: Future private lateinit var animateFuture: Future - private var defaultPosition: Transform - private var targetFrame: AttachedFrame - private var lookAt: LookAt + private lateinit var defaultPosition: Transform + private lateinit var targetFrame: AttachedFrame + private lateinit var lookAt: LookAt + init { - val robotFrame = qiContext.actuation.robotFrame() - defaultPosition = TransformBuilder.create().fromXTranslation(100.0) - targetFrame = robotFrame.makeAttachedFrame(defaultPosition) - lookAt = LookAtBuilder.with(qiContext).withFrame(targetFrame.frame()).build() - lookAt.addOnStartedListener { - Log.i(TAG, "LookAt started") + qiContext.actuation.async().gazeFrame().andThenConsume { robotFrame -> + defaultPosition = TransformBuilder.create().fromXTranslation(100.0) + targetFrame = robotFrame.makeAttachedFrame(defaultPosition) + lookAt = LookAtBuilder.with(qiContext).withFrame(targetFrame.frame()).build() + lookAt.addOnStartedListener { + Log.i(TAG, "LookAt started") + } + if (startAfterInitialization) start() + } + } + + fun start() { + Log.d(TAG, "start") + + if (!::lookAt.isInitialized) { + startAfterInitialization = true + return } + + if (isRunning) return + lookAtFuture = lookAt.async().run() lookAtFuture.thenConsume { when { @@ -51,13 +67,33 @@ class RemoteRobotController(context: QiContext) { lookAtFuture.isCancelled -> Log.e(TAG, "LookAt cancelled") } } + + isRunning = true } - fun updateTarget(newLeftJoystickX: Float, newLeftJoystickY: Float, newRightJoystickX: Float, newRightJoystickY: Float) { - Log.d(TAG, "updateTarget newLeftJoystickX=$newLeftJoystickX " + - "newLeftJoystickY=$newLeftJoystickY " + - "newRightJoystickX=$newRightJoystickX " + - "newRightJoystickY=$newRightJoystickY") + fun stop() { + Log.d(TAG, "stop") + + if (!isRunning) return + + lookAtFuture.requestCancellation() + animateFuture.requestCancellation() + + isRunning = false + } + + fun updateTarget( + newLeftJoystickX: Float, + newLeftJoystickY: Float, + newRightJoystickX: Float, + newRightJoystickY: Float + ) { + Log.d( + TAG, "updateTarget newLeftJoystickX=$newLeftJoystickX " + + "newLeftJoystickY=$newLeftJoystickY " + + "newRightJoystickX=$newRightJoystickX " + + "newRightJoystickY=$newRightJoystickY" + ) // Round values var roundedNewLeftJoystickX = 0 @@ -91,46 +127,59 @@ class RemoteRobotController(context: QiContext) { } private fun makeTranslation() { - Log.d(TAG, "makeTranslation currentLeftJoystickX=$currentLeftJoystickX currentLeftJoystickY=$currentLeftJoystickY") + Log.d( + TAG, + "makeTranslation currentLeftJoystickX=$currentLeftJoystickX currentLeftJoystickY=$currentLeftJoystickY" + ) + + if (!isRunning) return if (::animateFuture.isInitialized && !animateFuture.isDone) { animateFuture.requestCancellation() } else if (!(currentLeftJoystickX == 0 && currentLeftJoystickY == 0) && !isMoving) { isMoving = true - lookAt.policy = LookAtMovementPolicy.HEAD_ONLY - - val targetX = -currentLeftJoystickY.toDouble() - val targetY = -currentLeftJoystickX.toDouble() - - val animationString = "[\"Holonomic\", [\"Line\", [$targetX, $targetY]], 0.0, 40.0]" - val animation = AnimationBuilder.with(qiContext).withTexts(animationString).build() - val animate = AnimateBuilder.with(qiContext).withAnimation(animation).build() - animate.addOnStartedListener { - Log.i(TAG, "Animate started") - - if (!(targetX == -currentLeftJoystickY.toDouble() && targetY == -currentLeftJoystickX.toDouble())) { - animateFuture.requestCancellation() + lookAt.async().setPolicy(LookAtMovementPolicy.HEAD_ONLY).andThenConsume { + val targetX = -currentLeftJoystickY.toDouble() + val targetY = -currentLeftJoystickX.toDouble() + + val animationString = "[\"Holonomic\", [\"Line\", [$targetX, $targetY]], 0.0, 40.0]" + val animation = AnimationBuilder.with(qiContext).withTexts(animationString).build() + val animate = AnimateBuilder.with(qiContext).withAnimation(animation).build() + animate.addOnStartedListener { + Log.i(TAG, "Animate started") + + if (!(targetX == -currentLeftJoystickY.toDouble() && targetY == -currentLeftJoystickX.toDouble())) { + animateFuture.requestCancellation() + } } - } - animateFuture = animate.async().run() - animateFuture.thenConsume { - when { - animateFuture.isSuccess -> Log.i(TAG, "Animate finished with success") - animateFuture.hasError() -> Log.e(TAG, "Animate error: ${animateFuture.errorMessage}") - animateFuture.isCancelled -> Log.i(TAG, "Animate cancelled") + animateFuture = animate.async().run() + animateFuture.thenConsume { + when { + animateFuture.isSuccess -> Log.i(TAG, "Animate finished with success") + animateFuture.hasError() -> Log.e( + TAG, + "Animate error: ${animateFuture.errorMessage}" + ) + animateFuture.isCancelled -> Log.i(TAG, "Animate cancelled") + } + + lookAt.policy = LookAtMovementPolicy.HEAD_AND_BASE + isMoving = false + + makeTranslation() } - - lookAt.policy = LookAtMovementPolicy.HEAD_AND_BASE - isMoving = false - - makeTranslation() } } } private fun makeRotation() { - Log.d(TAG, "makeRotation currentRightJoystickX=$currentRightJoystickX currentRightJoystickY=$currentRightJoystickY") + Log.d( + TAG, + "makeRotation currentRightJoystickX=$currentRightJoystickX currentRightJoystickY=$currentRightJoystickY" + ) + + if (!isRunning) return if (currentRightJoystickX == 0 && currentRightJoystickY == 0) { targetFrame.update(defaultPosition) diff --git a/pepper-gamepad-root/sample-app/build.gradle b/pepper-gamepad-root/sample-app/build.gradle index 94a59b4..397e751 100755 --- a/pepper-gamepad-root/sample-app/build.gradle +++ b/pepper-gamepad-root/sample-app/build.gradle @@ -5,11 +5,11 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "com.softbankrobotics.peppergamepadsample" minSdkVersion 23 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 2 versionName "1.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/pepper-gamepad-root/sample-app/src/main/java/com/softbankrobotics/peppergamepadsample/MainActivity.kt b/pepper-gamepad-root/sample-app/src/main/java/com/softbankrobotics/peppergamepadsample/MainActivity.kt index 56d0065..16eb306 100755 --- a/pepper-gamepad-root/sample-app/src/main/java/com/softbankrobotics/peppergamepadsample/MainActivity.kt +++ b/pepper-gamepad-root/sample-app/src/main/java/com/softbankrobotics/peppergamepadsample/MainActivity.kt @@ -149,7 +149,7 @@ class MainActivity : Activity(), RobotLifecycleCallbacks, InputDeviceListener { } } remoteRobotController = RemoteRobotController(qiContext) - Log.i(TAG, "after RemoteRobotController instantiation") + remoteRobotController.start() } override fun onGenericMotionEvent(event: MotionEvent): Boolean { @@ -168,7 +168,12 @@ class MainActivity : Activity(), RobotLifecycleCallbacks, InputDeviceListener { if (::remoteRobotController.isInitialized) { thread { - remoteRobotController.updateTarget(leftJoystickX, leftJoystickY, rightJoystickX, rightJoystickY) + remoteRobotController.updateTarget( + leftJoystickX, + leftJoystickY, + rightJoystickX, + rightJoystickY + ) } } else { Log.d(TAG, "@@@@@@@@@ not initialized") @@ -202,6 +207,7 @@ class MainActivity : Activity(), RobotLifecycleCallbacks, InputDeviceListener { override fun onRobotFocusLost() { Log.i(TAG, "onRobotFocusLost") qiContext = null + remoteRobotController.stop() } override fun onRobotFocusRefused(reason: String?) { diff --git a/pepper-gamepad-root/sample-app/src/main/res/values-fr/strings.xml b/pepper-gamepad-root/sample-app/src/main/res/values-fr/strings.xml index 423940a..4178a4e 100644 --- a/pepper-gamepad-root/sample-app/src/main/res/values-fr/strings.xml +++ b/pepper-gamepad-root/sample-app/src/main/res/values-fr/strings.xml @@ -1,8 +1,6 @@ Pepper Gamepad Sample - Connectez une manette pour utiliser l\'application. - Aucune manette détectée Génial, on part en balade! Prends ta manette, jette un oeil aux contrôles et on y va! 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. diff --git a/pepper-gamepad-root/sample-app/src/main/res/values/strings.xml b/pepper-gamepad-root/sample-app/src/main/res/values/strings.xml index da43336..b00196b 100755 --- a/pepper-gamepad-root/sample-app/src/main/res/values/strings.xml +++ b/pepper-gamepad-root/sample-app/src/main/res/values/strings.xml @@ -1,7 +1,5 @@ Pepper Gamepad Sample - No controller detected - Please connect a controller to use the app. Great, let\'s have fun together! Take the game pad, look at the controls and we\'re good to go! 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!