rosjava / android_apps

Applications built on top of the rosjava android libraries.
132 stars 112 forks source link

How can i reconnect with RosMaster #72

Open tomliu77 opened 6 years ago

tomliu77 commented 6 years ago

if i turn off wifi, and then i turing on ,app can't reconnect with my robot,show i close server and start it again or threre is some simple way?

jubeira commented 6 years ago

Hi @tomliu77, I guess you'd need to handle that case in your application manually; I really don't think that case is handled right now. You would need to detect when the WiFi goes back again, shut down all your nodes and launch them again.

The easy workaround is what you say: close the app and reopen it.

tomliu77 commented 6 years ago

@jubeira, thanks for your answer,I use nodeMainExecutorService.shutdownNodeMain() to shutdown all my nodes and use nodeMainExecutor.execute() to launch them again. But the question is , I see the callback onShutdownComplete() is called quieckly but the node looks like not shutdown competely, Because the number of thread haven't reduce . When I try to restart my nodes ,app chrashed with OOM

tomliu77 commented 6 years ago

@jubeira, by the way ,I have 18 nodes and I find 400+ thread in Android studio profiling , when i shutdown my nodes ,the number of thread will reduce to 60+ after 1min. Also, should i call an new NodeMainExecutorService when wifi has been reconnected?

tomliu77 commented 6 years ago

@jubeira, thanks for your answer again

jubeira commented 6 years ago

@tomliu77 I'm not 100% sure about this, but I think you should code forceShutdown in NodeMainExecutorService to shut down all the nodes and not just one. Note that it may take a while to try to disconnect nodes if you don't have connection to the Master, because your nodes will try to contact it and fail with some timeout. And taking a quick look at the code, yes, I would create a new NodeMainExecutorService when WiFi is reconnected because it acquires some locks on it and so on.

tomliu77 commented 6 years ago

@jubeira,Thanks for your advice. When I code forceShutdown in NodeMainExecutorService ,my Activity also finished immediately and I find this in RosActivity

  serviceListener = new NodeMainExecutorServiceListener() {
                @Override
                public void onShutdown(NodeMainExecutorService nodeMainExecutorService) {
                    // We may have added multiple shutdown listeners and we only want to
                    // call finish() once.
                    if (!RosActivity.this.isFinishing()) {
                        RosActivity.this.finish();
                   }
                }
            };

It's seems like I can not use this way ,so I delete RosActivity.this.finish() , but the number of thread in the background don't reduce immediately . Is there some way to shutdown nodes immediately and make them not contact Rosmaster until I restart NodeMainExecutorService?

jubeira commented 6 years ago

Hmm there's no standard way to do that that I know of... Let me explain. In ROS you always expect the Master to keep track of the list of registered nodes and topics. When a node shuts down, it tells the master to unregister itself; if there's no response, it may be because networking issues, and that's why there are timeouts. Bypassing all that sounds like a hack to me; you may find a way around it, but you may need to rewrite some code to access the thread running the nodes and kill it manually.

You could also lower the timeouts. If you go to rosjava_core, you will see timeouts here and there (search for keywords like "timeout" and "5000" or "10000"; most of them last 5 seconds). You can modify that, recompile rosjava_core, and use your custom version with low timeouts. In any case, that's just another hack. I think the "clean" and easy way for your problem is to restart the app, and kill the process that started the app when you shut it down. You can use

android.os.Process.killProcess(android.os.Process.myPid());

from your activity in onDestroy to do that.

jubeira commented 6 years ago

The real clean way would be to shut down all the nodes before turning off Wi Fi (that won't take long, because all the nodes will just unregister in the standard way without timeouts), but you may not have control over that.

tomliu77 commented 6 years ago

@jubeira,Thank you. It's seems like nodeMainExecutorService.getScheduledExecutorService().shutdownNow(); will work . if I find a better way ,I'll tell you the first time