-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updating hello-ros example with basic ui #101
base: kinetic
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the implementation using a Java activity which offloads the ROS work via JNI. Looks much cleaner like that. Indeed there is no need to use a native activity as long as we can trigger the ROS initialization and shutdown via JNI.
What I am missing is that the master URI and eventually ROS_IP is stored persistently, maybe using SharedPreferences.
Is it possible to place the settings controls in a separate dialog? Seems there is a built-in mechanism for that in Android, which configures SharedPreferences
. For a simple test app having the settings in the main activity might be fine, but for real-world apps you might want to hide the settings and start the application with the defaults loaded from preferences. If the master URI gets changed, most likely the application has to be restarted anyway because roscpp
cannot switch ROS master.
Last but not least: How complex is it to integrate the ROS master implementation of rosjava
, in order to offer the option to run a local master? This is just a nice-to-have.
Please also add some license headers to the added files.
@@ -4,7 +4,7 @@ android { | |||
compileSdkVersion 28 | |||
|
|||
defaultConfig { | |||
applicationId = 'com.example.hello_ros' | |||
applicationId = 'com.ros.example.hello_ros' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rosjava uses the org.ros
prefix. If we go away from com.example
, should we also use org
instead of com
following the registered internet domain? What is the convention here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd propose org.ros.android
as prefix and then .example.hello_ros
.
example_workspace/src/hello_world_example_app/app/src/main/cpp/main_thread.cpp
Outdated
Show resolved
Hide resolved
MainThread::MainThread(std::string name) : node_name(name) {} | ||
MainThread::~MainThread() {} | ||
|
||
bool MainThread::check_ros_master(std::string master_ip, std::string my_ip) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe my_ip
should be optional? On devices with only one interface the automatic detection implemented in ros::network::determineHost() works well for us on Android.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm now I moved it to remapping arguments so the IP address is also included there. I'm not sure if it's really needed in this implementation of ros::init
using ros::VP_string
.
In any case scanning the VP for the IP is a bit annoying (not worse than sending a map through JNI though, which is another option). In any case the Java side gets the IP for you, so from the user's point of view it's basically the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comment was actually independent on how the IP address is passed down to the native code and the exact parameter name. What I meant is that it should be possible to simply not set a ROS_IP like for Linux and leave it to roscpp
to choose a hostname or IP string wisely. At least for us that works well and would not require the user to manually enter the IP address of the device.
On the other hand ros::network::determineHost() prefers non-private IP addresses if there is more than one network interface, which is most likely not what we want on phones which have a connection to a cellular network.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll retest this tomorrow; if it works without setting the IP address I'd leave it in the activity as a text view (non-editable) for information purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, the IP address is not necessary. I'll change it to a read-only field to provide that information to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to make it optional (leave it empty)? In some cases, for example if you have a 3G connection and a Wifi connection, it is necessary to select one of them by setting the ROS_IP
(or ROS_HOSTNAME
).
I don't see much added value in showing the IP address to the user. If so, it should be exactly the same as ros::network::determineHost() found. It is available using ros::network::getHost(). In fact, it does not matter whether the string is an IP address or a hostname, as long as potential subscribers can reach the Android device using that name.
A spinner listing all available interfaces and their IP addresses would be ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that sounds good; let's make it an (optional) spinner: if the user doesn't specify any interface we shall send no remapping for the IP address and let ROS decide it.
example_workspace/src/hello_world_example_app/app/src/main/cpp/main_thread.cpp
Outdated
Show resolved
Hide resolved
...ce/src/hello_world_example_app/app/src/main/java/com/ros/example/hello_ros/MainActivity.java
Outdated
Show resolved
Hide resolved
...ce/src/hello_world_example_app/app/src/main/java/com/ros/example/hello_ros/MainActivity.java
Outdated
Show resolved
Hide resolved
mainThread.stop(); | ||
status = Status.WAITING; | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know roscpp
does not allow to initialize the node twice, so ros::init()
cannot be called twice within the same process, even if you call ros::shutdown()
in between. Given that this is true, does it make sense to allow to toggle the state between WAITING
and RUNNING
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #101 (comment); this seems to be working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It cannot if g_initialized
is not destroyed and reinitialized to its default value: It is only ever set to true
in init.cpp:469 and never reset. It might seem to work, but the new settings won't take effect. This behavior might be trivial to fix in roscpp, but without a patch you cannot change the master URI or ROS_IP without terminating the app or unloading all shared libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. So this would work only to start / stop the program using the same ROS master; in any case it still sounds somewhat useful to me. I'll add a note somewhere clarifying that the app should be restarted if the ROS master changes after the first connection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested the app today and as expected changes of the ROS master IP have no effect until the app is terminated by swiping it up or down in the app view.
a25652a
to
b49fa37
Compare
Update: I addressed some comments, adding support for remapping arguments and shared preferences.
Hmm I wouldn't go that way in this example. Using |
Okay, understood. |
} else { | ||
ROS_INFO("NO ROS MASTER."); | ||
} | ||
ros::start(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only call ros::start()
if ros::master::check()
returns true
?
Apparently ros::start()
tries to contact the master, logs
ros.roscpp: [registerPublisher] Failed to contact master at [x.x.x.x:11311]. Retrying...
and waits forever. Android then shows the "RosHello isn't responding" dialog.
Thanks for updating the UI and addressing comments.
Maybe the app requires some additional permissions to access network state? The documentation of getNetworkInterfaces() mentions that |
LGTM, except for this nice-to-have comment has not been addressed yet. Currently the app freezes if the ROS master cannot be reached, e.g. due to a typo in the IP address of the ROS master. Instead, Additionally, there is no reason to not allow alphanumeric host names instead of an IP address in the Feel free to apply these two changes, or not. |
This is base on the previous hello-ros sample app. I moved from NativeActivity to a normal java Activity, as I think it is better for this. We can also apply this changes to the other examples.
Note: Taking in account the comments here https://stackoverflow.com/questions/7815368/how-to-set-content-view-of-nativeactivity-to-component-created-in-java, NativeActivity can still be used.
Supersede #100