Open chadrockey opened 11 years ago
From markus.b...@gmail.com on November 06, 2012 14:32:29 Please see http://code.google.com/p/rosjava/issues/detail?id=150 for an updated patch for this issue.
Sorry for opening another issue for the same problem. Markus
This is regularly becoming a problem given phones often now utilise multiple interfaces at once. Problem code is in:
NodeConfiguration nodeConfiguration =
NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress(), getMasterUri());
nodeMainExecutor.execute(rosTextView, nodeConfiguration);
This code in the factory:
public static InetAddress newNonLoopback() {
for (InetAddress address : getAllInetAddresses()) {
// IPv4 only for now.
if (!address.isLoopbackAddress() && isIpv4(address)) {
return address;
}
}
throw new RosRuntimeException("No non-loopback interface found.");
}
results in just the first one listed getting lucky. Some information from the official java docs:
Multiple interface/address configurations were relatively rare when this API was designed, but multiple interfaces are the default for modern mobile devices (with separate wifi and radio interfaces), and the need to support both IPv4 and IPv6 has made multiple addresses commonplace. New code should thus avoid this method except where it's basically being used to get a loopback address or equivalent.
There are two main ways to get a more specific answer:
If you have a connected socket, you should probably use getLocalAddress() instead: that will give you the address that's actually in use for that connection. (It's not possible to ask the question "what local address would a connection to a given remote address use?"; you have to actually make the connection and see.)
That getLocalAddress
function is part of the Socket API.
Maybe what we can do is connect to the master, get the socket it is using and query that to work out what interface our phone has routed on?
Testies (albeit only one)! The following is some code from the implementation of a RosActivity
init
.
protected void init(NodeMainExecutor nodeMainExecutor) {
try {
java.net.InetAddress local_network_address;
java.net.Socket socket = new java.net.Socket(getMasterUri().getHost(), getMasterUri().getPort());
local_network_address = socket.getLocalAddress();
socket.close();
// Ye Olde:
// NodeConfiguration nodeConfiguration =
// NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress(), getMasterUri());
NodeConfiguration nodeConfiguration =
NodeConfiguration.newPublic(local_network_address.getHostAddress(), getMasterUri());
Talker talker = new Talker();
nodeMainExecutor.execute(talker, nodeConfiguration);
nodeMainExecutor.execute(rosTextView, nodeConfiguration);
} catch (IOException e) {
}
}
This works. @damonkohler can you think of cases where this would actually be a problem? Is this a method we can add to the InetAddressFactory suite? Or even better, bury under the hood of the NodeConfiguration constructors.
Unfortunately, just using the address that is used to connect to the master isn't good enough. For example, the master may be local and accessible via loopback but other nodes will be off the system and not accessible that way.
I don't think there's a good answer to this. The newNonLoopback() method is really just for convenience. I don't think it's necessarily rosjava's job to find the right address every time. That could lead to a lot of lag/overhead without some rather complicated/clever connection code.
However, I could see adding a drop down to the MasterChooser that would assist the user in selecting the correct interface.
Unfortunately, just using the address that is used to connect to the master isn't good enough. For example, the master may be local and accessible via loopback but other nodes will be off the system and not accessible that way.
Ah, I was mistaking the host address as being purely for negotiating with the ros master. Instead, this is like setting ROS_IP
for a node. Your suggestion of implementing it in the master chooser is a good one.
Original author: markus.b...@gmail.com (October 12, 2012 19:10:07)
InetAddressFactory.newNonLoopback() returns non-wifi network adapter on a phone
What steps will reproduce the problem?
What is the expected output? What do you see instead? App PubSubTutorial should connect to the masters URI and start publishing Messages. It should do so and use its wifi ip address in the topics information.
It does connect to the ROS master, but it propagates its UMTS/GSM ip address. This is, in my case, vsnet0 instead of wlan0. This ip address is obviously not useful for other nodes as they are unable to connect to it.
What version of the product are you using? On what operating system? Latest rosjava_core and android_core from 10.October 2012Android 4.1.1 . I do not know how to extract the exact version info from my installation.
Please provide any additional information below. vsnet0 is a PointToPoint interface, wlan0 is not. The attached patch checks if the first nonLoopback interface is a PointToPoint one. If not it should be the desired wifi interface.
Original issue: http://code.google.com/p/rosjava/issues/detail?id=147