Table des matières
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.
- 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
<uses-permission android:name="android.permission.INTERNET" />
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
<uses-permission android:name="android.permission.INTERNET" />
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.
- 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é.