Updated exercise handling code to make pepper more verbal
This commit is contained in:
@@ -40,4 +40,8 @@ public class Exercise {
|
|||||||
this.videoUrl = videoUrl;
|
this.videoUrl = videoUrl;
|
||||||
this.exerciseTimeInSeconds = exerciseTimeInSeconds;
|
this.exerciseTimeInSeconds = exerciseTimeInSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ExerciseFetchHandler {
|
||||||
|
void handle(Exercise exercise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,23 +18,28 @@ public class ExerciseManager {
|
|||||||
// The value of these property variables must be equivalent of
|
// The value of these property variables must be equivalent of
|
||||||
// the JSON data that the database sends back.
|
// the JSON data that the database sends back.
|
||||||
// If this is not the case then the exercise retrieval will fail.
|
// If this is not the case then the exercise retrieval will fail.
|
||||||
private static final String PROPERTY_MUSCLE_GROUP = "muscleGroup";
|
private static final String PROPERTY_EXERCISE_DURATION = "duration";
|
||||||
private static final String PROPERTY_DESC = "description";
|
private static final String PROPERTY_EXERCISE_ID = "exerciseId";
|
||||||
private static final String PROPERTY_IMAGE_URL = "imageUrl";
|
private static final String PROPERTY_MUSCLE_GROUP = "muscleGroup";
|
||||||
private static final String PROPERTY_VIDEO_URL = "videoUrl";
|
private static final String PROPERTY_SHORT_DESC = "shortDescription";
|
||||||
private static final String PROPERTY_NAME = "name";
|
private static final String PROPERTY_IMAGE_URL = "imageUrl";
|
||||||
private static final String PROPERTY_DATA = "data";
|
private static final String PROPERTY_VIDEO_URL = "videoUrl";
|
||||||
private static final String PROPERTY_EXERCISE_DURATION = "exerciseDuration";
|
private static final String PROPERTY_DESC = "description";
|
||||||
|
private static final String PROPERTY_PATH = "path";
|
||||||
|
private static final String PROPERTY_NAME = "name";
|
||||||
|
|
||||||
public static final int SENSOR_COUNT = 2;
|
public static final int SENSOR_COUNT = 2;
|
||||||
|
|
||||||
private static final String[] REQUIRED_PROPERTIES = {
|
private static final String[] REQUIRED_PROPERTIES = {
|
||||||
PROPERTY_MUSCLE_GROUP, PROPERTY_DESC, PROPERTY_IMAGE_URL,
|
PROPERTY_MUSCLE_GROUP, PROPERTY_DESC, PROPERTY_IMAGE_URL,
|
||||||
PROPERTY_VIDEO_URL, PROPERTY_NAME, PROPERTY_DATA,
|
PROPERTY_VIDEO_URL, PROPERTY_NAME, PROPERTY_PATH,
|
||||||
PROPERTY_EXERCISE_DURATION
|
PROPERTY_EXERCISE_DURATION, PROPERTY_EXERCISE_ID,
|
||||||
|
PROPERTY_SHORT_DESC
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final float DEFAULT_SEGMENT_SPEED = 1.0f;
|
public static final int DEFAULT_EXERCISE_REPETITIONS = 10;
|
||||||
|
public static final float DEFAULT_SEGMENT_SPEED = 1.0f;
|
||||||
|
public static final float EXERCISE_ERROR_MARGIN = 1.0f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for sending an HTTP request to the server.
|
* Function for sending an HTTP request to the server.
|
||||||
@@ -95,7 +100,7 @@ public class ExerciseManager {
|
|||||||
// Path data is split into two parts, due to the left and right hand.
|
// Path data is split into two parts, due to the left and right hand.
|
||||||
// If one wants to add support for more sensors, one will have to adjust the Exercise
|
// If one wants to add support for more sensors, one will have to adjust the Exercise
|
||||||
// class to support more paths.
|
// class to support more paths.
|
||||||
String[] leftRightData = content.get(PROPERTY_DATA).getAsString().split(";");
|
String[] leftRightData = content.get(PROPERTY_PATH).getAsString().split(";");
|
||||||
|
|
||||||
if ( leftRightData.length != SENSOR_COUNT)
|
if ( leftRightData.length != SENSOR_COUNT)
|
||||||
return null;
|
return null;
|
||||||
|
@@ -4,8 +4,7 @@ import android.os.Bundle;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
import com.example.fitbot.R;
|
import com.example.fitbot.R;
|
||||||
import com.example.fitbot.ui.activities.FitnessActivity;
|
import com.example.fitbot.util.NavigationManager;
|
||||||
import com.example.fitbot.ui.activities.MainActivity;
|
|
||||||
|
|
||||||
public class EndScreenActivity extends AppCompatActivity {
|
public class EndScreenActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ public class EndScreenActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_end_screen);
|
setContentView(R.layout.activity_end_screen);
|
||||||
|
|
||||||
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.homeButtonEndScreen, MainActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.homeButtonEndScreen, MainActivity.class);
|
||||||
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.startButtonEndScreen, FitnessActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.startButtonEndScreen, FitnessActivity.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,6 @@
|
|||||||
package com.example.fitbot.ui.activities;
|
package com.example.fitbot.ui.activities;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.VideoView;
|
import android.widget.VideoView;
|
||||||
|
|
||||||
import com.aldebaran.qi.sdk.QiContext;
|
import com.aldebaran.qi.sdk.QiContext;
|
||||||
@@ -14,7 +12,7 @@ import com.example.fitbot.R;
|
|||||||
import com.example.fitbot.exercise.Exercise;
|
import com.example.fitbot.exercise.Exercise;
|
||||||
import com.example.fitbot.exercise.ExerciseManager;
|
import com.example.fitbot.exercise.ExerciseManager;
|
||||||
import com.example.fitbot.ui.components.PersonalMotionPreviewElement;
|
import com.example.fitbot.ui.components.PersonalMotionPreviewElement;
|
||||||
import com.example.fitbot.util.ButtonNavigation;
|
import com.example.fitbot.util.NavigationManager;
|
||||||
import com.example.fitbot.util.FitnessCycle;
|
import com.example.fitbot.util.FitnessCycle;
|
||||||
import com.example.fitbot.util.processing.InputProcessor;
|
import com.example.fitbot.util.processing.InputProcessor;
|
||||||
|
|
||||||
@@ -56,7 +54,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
// Find the VideoView by its ID
|
// Find the VideoView by its ID
|
||||||
VideoView videoView = findViewById(R.id.videoView);
|
VideoView videoView = findViewById(R.id.videoView);
|
||||||
FitnessCycle.playVideo(videoView, this);
|
FitnessCycle.playVideo(videoView, this);
|
||||||
ButtonNavigation.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class);
|
||||||
// Implement your logic when the robot focus is gained
|
// Implement your logic when the robot focus is gained
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -73,22 +71,24 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
// This will provide the element with the appropriate dimensions for drawing
|
// This will provide the element with the appropriate dimensions for drawing
|
||||||
// the canvas properly.
|
// the canvas properly.
|
||||||
personalMotionPreviewElement.post(() -> {
|
personalMotionPreviewElement.post(() -> {
|
||||||
Exercise exercise = this.acquireExercise();
|
this.acquireExercise((exercise) -> {
|
||||||
if ( exercise == null) {
|
// Acquire paths from the exercise and provide them to the motion processor
|
||||||
return;
|
Vector3f[][] vectors = new Vector3f[][] {exercise.leftPath.getVectors(), exercise.rightPath.getVectors()};
|
||||||
}
|
|
||||||
// Acquire paths from the exercise and provide them to the motion processor
|
|
||||||
Vector3f[][] vectors = new Vector3f[][] {exercise.leftPath.getVectors(), exercise.rightPath.getVectors()};
|
|
||||||
|
|
||||||
motionProcessor = new InputProcessor(vectors, exercise.exerciseTimeInSeconds, SENSOR_SAMPLE_RATE);
|
motionProcessor = new InputProcessor(vectors, exercise.exerciseTimeInSeconds, SENSOR_SAMPLE_RATE);
|
||||||
|
|
||||||
personalMotionPreviewElement.provideQiContext(qiContext);
|
personalMotionPreviewElement.provideQiContext(qiContext);
|
||||||
personalMotionPreviewElement.initialize(exercise, motionProcessor, EXERCISE_COUNT);
|
personalMotionPreviewElement.initialize(exercise, motionProcessor, EXERCISE_COUNT);
|
||||||
|
|
||||||
motionProcessor.startListening();
|
motionProcessor.startListening();
|
||||||
motionProcessor.setInputHandler(personalMotionPreviewElement);
|
motionProcessor.setInputHandler(personalMotionPreviewElement);
|
||||||
|
}, (n) -> {
|
||||||
|
int randomMessageIndex = (int)Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length);
|
||||||
|
FitnessCycle.say(EXERCISE_NOT_FOUND_MESSAGES[randomMessageIndex], qiContext);
|
||||||
|
FitnessCycle.say(EXERCISE_NOT_FOUND_SEEK_HELP_MESSAGE, qiContext);
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
personalMotionPreviewElement.provideQiContext(qiContext);
|
|
||||||
|
|
||||||
// FitnessCycle.playVideo(qiContext, videoView, this);
|
// FitnessCycle.playVideo(qiContext, videoView, this);
|
||||||
}
|
}
|
||||||
@@ -97,28 +97,32 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
* Acquire an exercise from the ExerciseManager.
|
* Acquire an exercise from the ExerciseManager.
|
||||||
* Whenever the retrieval failed, it will have the robot say something to the user
|
* Whenever the retrieval failed, it will have the robot say something to the user
|
||||||
* to inform them about the issue.
|
* to inform them about the issue.
|
||||||
*
|
|
||||||
* @return The acquired exercise, or null if the exercise could not be retrieved.
|
|
||||||
*/
|
*/
|
||||||
public Exercise acquireExercise() {
|
public void acquireExercise(Exercise.ExerciseFetchHandler onSuccessfulFetch, Exercise.ExerciseFetchHandler onFailedFetch) {
|
||||||
Exercise exercise = ExerciseManager.retrieveExercise();
|
// For some stupid reason we cannot perform network operations on the main thread.
|
||||||
if ( exercise == null && this.qiContext != null)
|
// therefore we'll have to do it like this...
|
||||||
{
|
(new Thread(() -> {
|
||||||
int randomMessageIndex = (int)Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length);
|
Exercise exercise = ExerciseManager.retrieveExercise();
|
||||||
FitnessCycle.say(EXERCISE_NOT_FOUND_MESSAGES[randomMessageIndex], qiContext);
|
if ( exercise == null)
|
||||||
FitnessCycle.say(EXERCISE_NOT_FOUND_SEEK_HELP_MESSAGE, qiContext);
|
{
|
||||||
}
|
onFailedFetch.handle(null);
|
||||||
return exercise;
|
}
|
||||||
|
else {
|
||||||
|
onSuccessfulFetch.handle(exercise);
|
||||||
|
}
|
||||||
|
})).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRobotFocusLost() {
|
public void onRobotFocusLost() {
|
||||||
// Implement your logic when the robot focus is lost
|
QiSDK.unregister(this, this);
|
||||||
|
// Go to the main screen
|
||||||
|
NavigationManager.navigateToActivity(this, MainActivity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRobotFocusRefused(String reason) {
|
public void onRobotFocusRefused(String reason) {
|
||||||
// Implement your logic when the robot focus is refused
|
QiSDK.unregister(this, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,6 +131,5 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
QiSDK.unregister(this, this);
|
QiSDK.unregister(this, this);
|
||||||
this.motionProcessor.stopListening();
|
this.motionProcessor.stopListening();
|
||||||
this.motionProcessor = null;
|
this.motionProcessor = null;
|
||||||
this.personalMotionPreviewElement.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -5,7 +5,7 @@ import android.os.Bundle;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.example.fitbot.R;
|
import com.example.fitbot.R;
|
||||||
import com.example.fitbot.util.ButtonNavigation;
|
import com.example.fitbot.util.NavigationManager;
|
||||||
|
|
||||||
public class HelpActivity extends AppCompatActivity {
|
public class HelpActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ public class HelpActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_help);
|
setContentView(R.layout.activity_help);
|
||||||
|
|
||||||
ButtonNavigation.setupButtonNavigation(this, R.id.homeButtonHelp, MainActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.homeButtonHelp, MainActivity.class);
|
||||||
|
|
||||||
// Hide system UI
|
// Hide system UI
|
||||||
hideSystemUI();
|
hideSystemUI();
|
||||||
|
@@ -10,13 +10,12 @@ import android.support.v4.widget.DrawerLayout;
|
|||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
import com.example.fitbot.R;
|
import com.example.fitbot.R;
|
||||||
import com.example.fitbot.util.ButtonNavigation;
|
import com.example.fitbot.util.NavigationManager;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@@ -63,8 +62,8 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
if (getSupportActionBar() != null) {
|
if (getSupportActionBar() != null) {
|
||||||
getSupportActionBar().hide();
|
getSupportActionBar().hide();
|
||||||
}
|
}
|
||||||
ButtonNavigation.setupButtonNavigation(this, R.id.startButtonMain, FitnessActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.startButtonMain, FitnessActivity.class);
|
||||||
ButtonNavigation.setupButtonNavigation(this, R.id.helpButtonMain, HelpActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.helpButtonMain, HelpActivity.class);
|
||||||
|
|
||||||
/*---Tool Bar---*/
|
/*---Tool Bar---*/
|
||||||
setSupportActionBar(toolbar); // Make the toolbar act as the action bar
|
setSupportActionBar(toolbar); // Make the toolbar act as the action bar
|
||||||
|
@@ -2,7 +2,6 @@ package com.example.fitbot.ui.components;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
@@ -15,6 +14,7 @@ import com.example.fitbot.exercise.Exercise;
|
|||||||
import com.example.fitbot.ui.activities.EndScreenActivity;
|
import com.example.fitbot.ui.activities.EndScreenActivity;
|
||||||
import com.example.fitbot.ui.activities.FitnessActivity;
|
import com.example.fitbot.ui.activities.FitnessActivity;
|
||||||
import com.example.fitbot.ui.activities.MainActivity;
|
import com.example.fitbot.ui.activities.MainActivity;
|
||||||
|
import com.example.fitbot.util.NavigationManager;
|
||||||
import com.example.fitbot.util.FitnessCycle;
|
import com.example.fitbot.util.FitnessCycle;
|
||||||
import com.example.fitbot.util.processing.IInputHandler;
|
import com.example.fitbot.util.processing.IInputHandler;
|
||||||
import com.example.fitbot.util.processing.InputProcessor;
|
import com.example.fitbot.util.processing.InputProcessor;
|
||||||
@@ -105,25 +105,6 @@ public class PersonalMotionPreviewElement extends View implements IInputHandler
|
|||||||
projectVertex(new Vector3f(0, 0, -5.0f), getWidth(), getHeight()),
|
projectVertex(new Vector3f(0, 0, -5.0f), getWidth(), getHeight()),
|
||||||
projectVertex(new Vector3f(0, 0, 5.0f), getWidth(), getHeight())
|
projectVertex(new Vector3f(0, 0, 5.0f), getWidth(), getHeight())
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy()
|
|
||||||
{
|
|
||||||
if ( this.motionProcessor != null )
|
|
||||||
this.motionProcessor.stopListening();
|
|
||||||
|
|
||||||
this.motionProcessor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function for providing a QiContext to the PersonalMotionPreviewElement.
|
|
||||||
* This function will be called by the parent activity when the QiContext is available.
|
|
||||||
* Also say something nice to the user :)
|
|
||||||
*
|
|
||||||
* @param context The QiContext to provide.
|
|
||||||
*/
|
|
||||||
public void provideQiContext(QiContext context) {
|
|
||||||
this.qiContext = context;
|
|
||||||
|
|
||||||
// Handler that is called every time the motion processor receives new data.
|
// Handler that is called every time the motion processor receives new data.
|
||||||
this.motionProcessor.setInputHandler((rotationVector, deviceId) -> {
|
this.motionProcessor.setInputHandler((rotationVector, deviceId) -> {
|
||||||
@@ -133,27 +114,29 @@ public class PersonalMotionPreviewElement extends View implements IInputHandler
|
|||||||
|
|
||||||
if ( this.motionProcessor.hasFinished())
|
if ( this.motionProcessor.hasFinished())
|
||||||
{
|
{
|
||||||
|
// If for some reason the parent activity is not defined,
|
||||||
|
// move back to the main screen.
|
||||||
if ( this.parentActivity == null)
|
if ( this.parentActivity == null)
|
||||||
{
|
{
|
||||||
// Move to main screen
|
// Move to main screen
|
||||||
this.destroy();
|
NavigationManager.navigateToActivity(getContext(), MainActivity.class);
|
||||||
Intent intent = new Intent(getContext(), MainActivity.class);
|
|
||||||
getContext().startActivity(intent);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Move on to the next exercise, or finish.
|
// Move on to the next exercise, or finish.
|
||||||
if ( this.exerciseCount > 0 )
|
if ( this.exerciseCount > 0 )
|
||||||
{
|
{
|
||||||
this.exerciseCount--;
|
this.exerciseCount--;
|
||||||
this.exercise = this.parentActivity.acquireExercise();
|
this.parentActivity.acquireExercise((newExercise) -> {
|
||||||
this.motionProcessor.useExercise(this.exercise);
|
this.motionProcessor.useExercise(newExercise);
|
||||||
|
}, (failed) -> {
|
||||||
|
// Move to main screen
|
||||||
|
NavigationManager.navigateToActivity(getContext(), MainActivity.class);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Finish the exercise.
|
// Finish the exercise.
|
||||||
this.destroy();
|
NavigationManager.navigateToActivity(getContext(), EndScreenActivity.class);
|
||||||
Intent intent = new Intent(getContext(), EndScreenActivity.class);
|
|
||||||
getContext().startActivity(intent);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,6 +151,17 @@ public class PersonalMotionPreviewElement extends View implements IInputHandler
|
|||||||
if (this.vectors.size() > 100)
|
if (this.vectors.size() > 100)
|
||||||
this.vectors.poll();
|
this.vectors.poll();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function for providing a QiContext to the PersonalMotionPreviewElement.
|
||||||
|
* This function will be called by the parent activity when the QiContext is available.
|
||||||
|
* Also say something nice to the user :)
|
||||||
|
*
|
||||||
|
* @param context The QiContext to provide.
|
||||||
|
*/
|
||||||
|
public void provideQiContext(QiContext context) {
|
||||||
|
this.qiContext = context;
|
||||||
|
|
||||||
if (this.qiContext == null)
|
if (this.qiContext == null)
|
||||||
return;
|
return;
|
||||||
|
@@ -7,6 +7,8 @@ import android.util.Log;
|
|||||||
import android.widget.VideoView;
|
import android.widget.VideoView;
|
||||||
|
|
||||||
import com.aldebaran.qi.sdk.builder.SayBuilder;
|
import com.aldebaran.qi.sdk.builder.SayBuilder;
|
||||||
|
import com.aldebaran.qi.sdk.object.conversation.Phrase;
|
||||||
|
import com.aldebaran.qi.sdk.object.conversation.Say;
|
||||||
import com.aldebaran.qi.sdk.object.locale.Language;
|
import com.aldebaran.qi.sdk.object.locale.Language;
|
||||||
import com.aldebaran.qi.sdk.object.locale.Locale;
|
import com.aldebaran.qi.sdk.object.locale.Locale;
|
||||||
import com.aldebaran.qi.sdk.object.locale.Region;
|
import com.aldebaran.qi.sdk.object.locale.Region;
|
||||||
@@ -17,19 +19,25 @@ import com.aldebaran.qi.sdk.builder.AnimationBuilder;
|
|||||||
import com.aldebaran.qi.sdk.object.actuation.Animate;
|
import com.aldebaran.qi.sdk.object.actuation.Animate;
|
||||||
import com.aldebaran.qi.sdk.object.actuation.Animation;
|
import com.aldebaran.qi.sdk.object.actuation.Animation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class FitnessCycle extends AppCompatActivity {
|
public class FitnessCycle extends AppCompatActivity {
|
||||||
|
|
||||||
private static final Locale DUTCH_LOCALE = new Locale(Language.DUTCH, Region.NETHERLANDS);
|
private static final Locale DUTCH_LOCALE = new Locale(Language.DUTCH, Region.NETHERLANDS);
|
||||||
|
private static final BlockingQueue<PepperSpeechEntry> MESSAGE_QUEUE = new LinkedBlockingQueue<>();
|
||||||
|
private static boolean SPEECH_ACTIVE = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for executing a movement animation a certain number of times
|
* Function for executing a movement animation a certain number of times
|
||||||
* on the robot
|
* on the robot
|
||||||
*
|
*
|
||||||
* @param Exercise The name of the exercise to perform
|
* @param Exercise The name of the exercise to perform
|
||||||
* @param Reps The number of repetitions to perform
|
* @param Reps The number of repetitions to perform
|
||||||
* @param qiContext The QiContext to use
|
* @param qiContext The QiContext to use
|
||||||
*/
|
*/
|
||||||
public static void executeMovement(String Exercise, int Reps, QiContext qiContext) {
|
public static void executeMovement(String Exercise, int Reps, QiContext qiContext) {
|
||||||
@@ -59,35 +67,46 @@ public class FitnessCycle extends AppCompatActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for making the robot say something with DUTCH_LOCALE as locale
|
* Function for making the robot say something with DUTCH_LOCALE as locale
|
||||||
|
*
|
||||||
* @param phrase The phrase to make the robot say
|
* @param phrase The phrase to make the robot say
|
||||||
* @param ctx The QiContext to use
|
* @param ctx The QiContext to use
|
||||||
*/
|
*/
|
||||||
public static void say(String phrase, QiContext ctx)
|
public static void say(String phrase, QiContext ctx) {
|
||||||
{
|
|
||||||
say(phrase, ctx, DUTCH_LOCALE);
|
say(phrase, ctx, DUTCH_LOCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for making the robot say something with a specific locale
|
* Function for making the robot say something with a specific locale
|
||||||
|
*
|
||||||
* @param phrase The phrase to make the robot say
|
* @param phrase The phrase to make the robot say
|
||||||
* @param ctx The QiContext to use
|
* @param ctx The QiContext to use
|
||||||
* @param locale The locale to use
|
* @param locale The locale to use
|
||||||
*/
|
*/
|
||||||
public static void say(String phrase, QiContext ctx, Locale locale)
|
public static void say(String phrase, QiContext ctx, Locale locale) {
|
||||||
{
|
// If the robot is already speaking, add the phrase to the queue
|
||||||
SayBuilder
|
MESSAGE_QUEUE.add(new PepperSpeechEntry(phrase, ctx, locale));
|
||||||
.with(ctx)
|
processMessageQueue();
|
||||||
.withLocale(locale)
|
}
|
||||||
.withText(phrase)
|
|
||||||
.build()
|
private static synchronized void processMessageQueue() {
|
||||||
.run();
|
if (SPEECH_ACTIVE)
|
||||||
|
return;
|
||||||
|
PepperSpeechEntry nextPhrase = MESSAGE_QUEUE.poll();
|
||||||
|
if (nextPhrase != null) {
|
||||||
|
SPEECH_ACTIVE = true;
|
||||||
|
Say say = nextPhrase.getSay();
|
||||||
|
say.async().run().andThenConsume(future -> {
|
||||||
|
SPEECH_ACTIVE = false;
|
||||||
|
processMessageQueue(); // Process next item in the queue
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for playing a video in a VideoView
|
* Function for playing a video in a VideoView
|
||||||
*
|
*
|
||||||
* @param videoView The VideoView to play the video in
|
* @param videoView The VideoView to play the video in
|
||||||
* @param context The context to use
|
* @param context The context to use
|
||||||
*/
|
*/
|
||||||
public static void playVideo(VideoView videoView, Context context) {
|
public static void playVideo(VideoView videoView, Context context) {
|
||||||
// Set up the video player
|
// Set up the video player
|
||||||
@@ -105,4 +124,24 @@ public class FitnessCycle extends AppCompatActivity {
|
|||||||
Log.e("FitnessActivity", "VideoView is null. Check your layout XML.");
|
Log.e("FitnessActivity", "VideoView is null. Check your layout XML.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class PepperSpeechEntry {
|
||||||
|
public String phrase;
|
||||||
|
public QiContext context;
|
||||||
|
public Locale locale;
|
||||||
|
|
||||||
|
public PepperSpeechEntry(String phrase, QiContext context, Locale locale) {
|
||||||
|
this.phrase = phrase;
|
||||||
|
this.context = context;
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Say getSay() {
|
||||||
|
return SayBuilder
|
||||||
|
.with(context)
|
||||||
|
.withLocale(locale)
|
||||||
|
.withText(phrase)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -6,7 +6,10 @@ import android.content.Intent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
public class ButtonNavigation {
|
import com.example.fitbot.ui.activities.FitnessActivity;
|
||||||
|
import com.example.fitbot.ui.activities.MainActivity;
|
||||||
|
|
||||||
|
public class NavigationManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up a button to navigate to a different activity when clicked.
|
* Sets up a button to navigate to a different activity when clicked.
|
||||||
@@ -23,4 +26,15 @@ public class ButtonNavigation {
|
|||||||
currentActivity.finish();
|
currentActivity.finish();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to the target activity.
|
||||||
|
*
|
||||||
|
* @param currentContext The current context
|
||||||
|
* @param targetActivity The target activity
|
||||||
|
*/
|
||||||
|
public static void navigateToActivity(Context currentContext, Class<? extends Activity> targetActivity) {
|
||||||
|
Intent intent = new Intent(currentContext, targetActivity);
|
||||||
|
currentContext.startActivity(intent);
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user