======== Android ========
===== ROS Android =====
Il existe plusieurs méthodes pour utiliser ROS sur un système Android.
- Portage Java de ROS avec le package Android [[http://wiki.ros.org/android]]
- Avec le NDK d'Android et cross-compilation des libs ROS. [[http://wiki.ros.org/android_ndk/Tutorials]]
La deuxième méthode permet d'assurer la compatibilité avec l'ensemble des codes C++ existants et une meilleur performance.
===== Tutoriel: ROS only =====
Construction d'un projet de test avec Android Studio et ROS. Ce tuto permet de lancer un noeud ROS sans avoir besoin d'une //Android Activity//.
Tout d'abord, récupérer (ou cross-compiler) ROS pour les systèmes Android.
* Téléchargement direct [[https://github.com/creativa77/roscpp_android/releases/download/v1.0/roscpp_android_ndk.tar.gz]]
* Tuto pour la cross-compilation [[http://wiki.ros.org/android_ndk/Tutorials/BuildingNativeROSPackages]]
(Déziper et) Placer le dossier ''roscpp_android_ndk'' à l'endroit voulu (Dans le dossier ''AndroidStudioProjects'' par exemple).
Ensuite, récupérer le projet de test sur le Redmine du LAAS. Ce projet peut servir de base à un projet plus conséquent.
[[https://redmine.laas.fr/projects/lumus/repository]] cloner le dépot Lumus. Le projet de base est contenu dans le dossier simpleROS.
Le projet test permet de lancer une node ROS sur un dispositif Android. Cette node écoute le topic ''/chatter'' et publie sur le topic ''/a_chatter''.
Ouvrir le projet avec Android studio
Dans l'arborescence projet, ouvrir ''app/cpp/sample_app/src/test.cpp'' qui contient le code C++ ROS
Modifier les valeurs des adresses ip pour les faire correspondre à votre configuration réseau.
// Set master workstation ip : __master
// Set android device ip : __ip
char *argv[] = {"nothing_important" , "__master:=http://192.168.150.1:11311", "__ip:=192.168.150.10"};
Dans l'arborescence projet, ouvrir ''External Build Files/Android.mk'' qui permet de configurer le build des modules NDK du projet (dans notre cas ROS)
Modifier la valeur ''NDK_MODULES_PATH'' par celle du dossier qui contient le dossier ''roscpp_android_ndk''. Cette variable référence le dossier contenant les modules NDK de l'application.
Ne pas oublier d'activer l'accès réseu pour le dispositif android. Dans ''AndroidManifest.xml''
Ensuite compiler l'application avec Android Studio (CTRL+F9).
Il faut maintenant lancer ROS sur la machine principale.
:!: Ne pas oublier de modifier les variables ''ROS_MASTER_URI'' et ''ROS_IP'' avec l'adresse IP de votre machine sur le réseau. ''ROS_MASTER_URI'' doit être identique à celle que vous avez modifier dans le code précédemment.
:!: La machine principale et l'appareil Android doivent être sur le même réseau. L'application [[https://play.google.com/store/apps/details?id=ua.com.streamsoft.pingtools&hl=fr]] permet de tester la connectivité réseau sur Android.
Dans 3 terminaux différents, lancer :
roscore
Connecter (USB) votre appareil et lancer l'application depuis Android Studio (SHIFT+F10).
rostopic pub /chatter std_msgs/String 'Hello!' -r 1
rostopic echo /a_chatter
Si tout fonctionne, la sortie console retourne
data: hello world from android ndk 1
data: hello world from android ndk 2
data: hello world from android ndk 3
Il est possible de surveiller le déroulement de l'application Android sur l'appareil avec ''Android Monitor'' sur Android Studio.
===== Tutoriel: ROS avec une Android Activity =====
Avant toute chose, il faut s'assurer que la lib ROS/Android est correctement mise en place dans le pprojet. Se réféerer au tuto précédent pour les détails. Exemple de fichier NDK build Android.mk :
LOCAL_PATH := $(call my-dir)
NDK_MODULES_PATH:= $(call my-dir)/../../../../../..
include $(CLEAR_VARS)
LOCAL_MODULE := ros_main
LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/ros/jniCalls
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ros/nativeCode
FILE_LIST := $(wildcard $(LOCAL_PATH)/src/ros/jniCalls/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/src/ros/nativeCode/*.cpp)
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_LDLIBS := -landroid -llog
LOCAL_STATIC_LIBRARIES := roscpp_android_ndk
include $(BUILD_SHARED_LIBRARY)
#import ros ndk with custom directory location
$(call import-add-path, $(NDK_MODULES_PATH) )
$(call import-module,roscpp_android_ndk)
Afin de ne pas bloquer l'execution de l'UI Android il est important de lancer les nodes ROS sur des threads différents. Un exemple de //class// pour réponder à cette contrainte :
public class ROSThread implements Runnable {
private Thread m_thread;
public ROSThread() {
this.m_thread = new Thread(this);
}
public void rosrun(){
m_thread.start();
}
@Override
public void run() {
startROSNode();
}
//load C/C++ shared library
static
{
System.loadLibrary("ros_main");
}
private native void startROSNode();
}
L'implémentation de ''private native void startROSNode();'' est une fonction C++ JNI qui lance le noeud ROS. Exemple :
JNIEXPORT void JNICALL Java_com_laas_simpleAR_ROSThread_startROSNode(JNIEnv* env, jobject obj)
{
android_main();
return;
}
On retrouve dans ''android_main()'' un noeud ROS habituel :
void android_main() {
ros::init(...);
ros::NodeHandle n;
ros::WallRate loop_rate(100);
while(ros::ok()){
ros::spinOnce();
loop_rate.sleep();
}
}
Ne pas oublier d'activer l'accès réseu pour le dispositif android. Dans ''AndroidManifest.xml''
===== Liens intéressants - Intégration OpenGL, OpenCV, ROS... etc. =====
* [[http://wiki.ros.org/android_ndk/Tutorials/SimpleNativeActivityApplication]] Pour plus d'infos. (04/17) Cette partie du tuto officiel ROS NDK n'est plus à jour avec les outils actuels.
* [[https://github.com/DeepBlue14/DanRosJCxxPrac]] Exemple de projet ROS Android multithreadé. La partie Android + ROS fonctionne mais la partie GUI n'est pas fonctionnelle.
* DOC NDK: [[https://developer.android.com/studio/projects/add-native-code.html]]
* Exemples d'utilisation [[https://github.com/googlesamples/android-ndk/tree/master]]
* Exemple utilisation avec natif OPENGL ES 1.0 et Java [[https://github.com/tsaarni/android-native-egl-example]] Explication sur SurfaceView utilisée ici [[https://developer.android.com/reference/android/view/SurfaceView.html]]
* Post/Tuto sur la mise en place d'OpenGL 2.0/3.0 (voir autres liens pour OpenCV, application AR ... etc.)[[http://www.anandmuralidhar.com/blog/android/gles-context/]] ndk_helper explication [[https://developer.android.com/ndk/samples/sample_teapot.html]]
* JNI vs NativeActivity [[http://stackoverflow.com/questions/13624499/android-ndk-nativeactivity-vs-jni-lib]]
* Installation OpenCV [[http://stackoverflow.com/questions/27406303/opencv-in-android-studio]]
* Prebuilt libraries for android [[https://kvurd.com/blog/compiling-a-cpp-library-for-android-with-android-studio/]]
* Crosscompilation Android script pour la toolchain [[https://gist.github.com/nddrylliog/4688209]]
* Apriltag ros kinetic [[https://github.com/xenobot-dev/apriltags_ros]]
=== ROS Android et snapdragon (used in Lumus DK50) ===
[[https://developer.qualcomm.com/blog/ros-support-qualcomm-snapdragon-bringing-arm-robotics]]
ROS Android et fastCV:
[[https://developer.qualcomm.com/blog/open-source-robotics-foundation-extends-support-qualcomm-snapdragon-processors]]
===== RVIZ on Android =====
Projet original rviz_for_android : [[https://bitbucket.org/zimmrmn3/rviz-for-android/wiki/Home]]
Le projet date de ~2012, il a été réalisé par un étudiant chez Willow Garage. Le projet est exclusivement en Java avec utilisation de ROSJava, du binding OpenGL ES Java, et certaines lib sont compilées avec le NDK.
**Le projet n'est pas un portage complet sur Android des fonctionnalités de RVIZ sur Desktop.**
Page Willow Garage du projet : [[http://www.willowgarage.com/blog/2012/09/24/rviz-android-0]]
==== Installation et Utilisation ====
- Télécharger l'APK et le serveur python: [[https://bitbucket.org/zimmrmn3/rviz-for-android/downloads/]].
- Télécharger les sources du package ROS tf_throttle: [[https://github.com/ros-interactive-manipulation/pr2_object_manipulation/tree/groovy-devel/applications/tf_throttle]]. Cette node permet de limiter la fréquence de publication des tfs pour ne pas saturer le réseau/dispositif Android.
Installer le package comme un package ROS classique.[[http://wiki.ros.org/ROS/Tutorials/CreatingPackage]]
:!: Pour compiler et installer avec catkin_make des modifications sont à effectuer :
Dans le package :
rm Makefile
Remplacer l'intégralité du contenu de CMakeLists.txt par :
cmake_minimum_required(VERSION 2.8.3)
project(tf_throttle)
find_package(catkin REQUIRED COMPONENTS geometry_msgs roscpp tf)
catkin_package( CATKIN_DEPENDS geometry_msgs roscpp tf)
include_directories(include
${catkin_INCLUDE_DIRS}
)
add_executable(tf_throttle src/tf_throttle.cpp)
target_link_libraries(tf_throttle ${catkin_LIBRARIES})
S'assurer que l'on peut correctement lancer la node.
rosrun tf_throttle tf_throttle
- Connecter les machines sur le même réseau. S'assurer que les machines peuvent communiquer (ping, ports... etc.)
- Lancer ROS sur le PC.
export ROS_IP=${IP_PC_SUR_RESEAU_ROS}
export ROS_MASTER_URI=http://${ROS_IP}:11311
roscore
- Lancer le serveur python
chmod +x server.py
./server.py
Le serveur python permet avec des requêtes HTTP d'interagir avec le PC depuis le dispositif Android. Il donne la possibilité de lancer/stopper des des nodes sur le PC distant et de gérer les fichiers URDF pour l'affichage des modèles 3D des robots. Plus d'info ici : Using the Python Server [[https://bitbucket.org/zimmrmn3/rviz-for-android/wiki/Contributing]]. C'est également lui qui lance tf_throttle.
- Installer l'application sur un dispositif Android.
adb install rviz_for_android.apk
- Lancer l'application.
- Renseigner l'adresse IP du PC qui a lancé le roscore
http://${IP_PC_SUR_RESEAU_ROS}:11311
- Cliquer sur "Layers" -> "Add" et choisir l'objet à afficher
==== Extensions ====
Le projet original a été modifié afin de pouvoir être utilisé avec la version Kinetic de ROS, les nouvelles versions d'Android et d'Android Studio. L'utilisation de l'application (compilé avec le projet) a été testé sur le Lumus DK50 (Android 4.0) et un WileyFox Swift (Android 7.0).
Le projet a donné lieu à une modification mineure du tutoriel ROS pour l'utilisation avec Android. [[http://wiki.ros.org/android/Tutorials/kinetic/Installation%20-%20Android%20Studio%20Development%20Environment]]\\
answers.ros [[https://answers.ros.org/question/273664/ros-and-android-with-kinetic-and-android-studio/?comment=273895#post-id-273895]]
Le projet modifié se trouve ici : [[https://redmine.laas.fr/projects/rviz_for_android/repository]].
Modifier le fichier ''local.properties''
ndk.dir=/chemin/NDK/Android/
sdk.dir=/home/tristan/Android/Sdk
:!: Si erreurs "AGPBI", activer multidex qui permet de casser la limite du nombre de méthodes [[https://developer.android.com/studio/build/multidex.html]].
:!: Si UI invisible regarder couleur des textes/backgrounds et compatibilité avec le thème utilisé (Il peut arriver que du texte sombre se retrouve sur un fond noir). Il peut aussi s'agir d'un mauvais "scaling" de l'UI à la taille de l'écran. L'auteur de l'application recommande une tablette de plus de 8 pouces.
:!: L'application est difficilement testable sur simulateur due à l'utilisation d'OpenGL ES 2.0.
== Ajout UI et Comportements Caméras ==
Il est possible d'étendre les interfaces proposées pour ajouter des nouveaux éléments affichables et des comportements caméras spécifiques.
Plus d'infos : [[https://bitbucket.org/zimmrmn3/rviz-for-android/wiki/Contributing]]
Caméra FPS attachée à une TF
- Ajouter une caméra (ou utiliser celle par défaut)
- Sélectionner dans "Fixed Frame" la TF de suivi de camera. Cette TF devient l'origine du monde affiché.
- Sélectionner dans "Follow" la TF choisie à l'étape précédente. L'application recalcule l'affichage du monde en suivant cette TF.
La caméra est maintenant attachée à la TF. elle est orientée le long de l'axe X (en rouge sur ROS) et son axe Z (en bleu sur ROS) est orienté vers le haut.
:!: A ce jour, les comportements de caméras n'utilisent pas l'interface Camera et le polymorphisme comme il serait normal de faire. Cela à cause du fait que modifier l'objet caméra dans la partie rendu provoque des effets de bords (affichage vide, erreur de matrices modèle ... etc). Il est plus facile, avec le code existant, d'utiliser un objet commun Camera lié au rendu et de spécialiser les méthodes de calcul de la matrice de vue. Actuellement pour changer de type de camera il est nécessaire de recompiler l'application en modifiant le type de camera dans les classes VisualizationView et MainActivity.
== Publication ROS des capteurs ==
:!: Activer autorisation GPS et Camera dans les paramètres de l'appareil Android sinon l'application crashera au démarrage.
Topics publiés :
/camera/image (camera 1)
/camera2/image (camera 2 Lumus)
/android/fix (GPS)
/android/imu (IMU)
Il est nécessaire d'avoir un rendu sur l'écran des lunettes pour obtenir les images de la caméra.
https://stackoverflow.com/questions/6756888/android-camera-image-size (changer résolution)
https://stackoverflow.com/questions/9160221/why-images-resolution-from-camera-picturecallback-is-the-size-of-previewsize (attention au ration avec pictureSize et previewSize)
:!: La partie GPS de l'application a été testée avec succès sur un autre appareil Android que le Lumus (Wiley Fox 7.0). Sur ce dernier, le GPS semble ne pas fonctionner correctement. Sur le site des specs du Lumus, il est écrit " GPS data is available upon wireless connection to Android smartphone". Après avoir connecté un smartphone (réseau local avec accès internet partagé), testé les différents modes de localisation l'application ne publie pas sur le topic. Le GPS est pourtant bien activé sur l'appareil. Sur Google Map, le Lumus ne parvient pas non plus à se localiser...
===== Programmation sur les lunettes Lumus =====
Attention à la version NDK utilisé. Version NDK 10e à utiliser tant que native_app_glue est utilisé.