I am currently developing an indoor augmented reality navigation android application and I am struggling using Google ARCore with Sceneform to create a navigation path from my current location to the destination (my question is about rendering and displaying, I already have my location necessities sorted out).
If someone could describe to me conceptually, or with code, a good starting strategy to iteratively render an arrowRenderable at different positions I would be very appreciative (for example, do I use Poses, setWorldPosition(), setLocalPosition(), etc...). I can convert (lat,long) to camera space as well so I am really looking to understand ARCore rendering better.
In regards to my implementation, I am using IndoorAtlas to handle my indoor positioning. The IndoorAtlas Android SDK comes with a wayfinding capability that creates routes from your current location to a destination (this is loaded in from a previously set wayfinding graph through IndoorAtlas online toolset). These routes are composed of legs that have a beginning and ending (lat,long) coordinates. What I am trying to do is render objects in AR iteratively along the ending (lat,long) coordinates.
Thank you in advance and please let me know if you would like additional information.
Here is an example of one implementation I tried:
public void createNavigationPath() {
// loop through the wayfinding route
for (IARoutingLeg leg : mCurrentRoute) {
// current loc
Location currentLoc = new Location("Current Location");
currentLoc.setLatitude(mLocation.latitude);
currentLoc.setLongitude(mLocation.latitude);
// end of wayfinding route segment
Location legEnd = new Location("Leg End");
legEnd.setLatitude(leg.getEnd().getLatitude());
legEnd.setLongitude(leg.getEnd().getLongitude());
// conversion from (lat,long) to camera space
// conversion implementation credit:
// https://github.com/dat-ng/ar-location-based-android
float[] currentLocationInECEF = WSG84toECEF(currentLoc);
float[] pointInECEF = WSG84toECEF(legEnd);
float[] pointInENU = ECEFtoENU(currentLoc, currentLocationInECEF, pointInECEF);
float[] cameraCoordinateVector = new float[4];
Matrix.multiplyMV(cameraCoordinateVector, 0, mRotatedProjectionMatrix, 0, pointInENU, 0);
Frame frame = arFragment.getArSceneView().getArFrame();
// cameraCoordinateVector[2] is z, that always less than 0 to display on right position
// if z > 0, the point will display on the opposite
if (cameraCoordinateVector[2] < 0) {
float x = (0.5f + cameraCoordinateVector[0] / cameraCoordinateVector[3]) * arFragment.getArSceneView().getWidth();
float y = (0.5f - cameraCoordinateVector[1] / cameraCoordinateVector[3]) * arFragment.getArSceneView().getHeight();
// Pose pose = new Pose(new float[]{x,y,cameraCoordinateVector[2]}, new float[]{0,0,0});
Anchor anchor = arFragment.getArSceneView().getSession().createAnchor(frame.getCamera().getPose().compose(Pose.makeTranslation(x,y,cameraCoordinateVector[2])).extractTranslation());
AnchorNode anchorNode = new AnchorNode(anchor);
Node tempNode = new Node();
tempNode.setParent(anchorNode);
tempNode.setRenderable(arrowRenderable);
Log.d(TAG, "Render Completed");
}
}
}
In my onCreate:
// set update listener on the AR scene for every frame
arFragment.getArSceneView()
.getScene()
.addOnUpdateListener(
frameTime -> {
// check if renderables have finished loading
if(!hasFinishedLoading) {
return;
}
// check if AR is active
Frame frame = arFragment.getArSceneView().getArFrame();
if (frame == null) {
return;
}
if (frame.getCamera().getTrackingState() != TrackingState.TRACKING) {
return;
}
// check if a destination is selected and a current location is reported
if(IAHelper.mDestination != null && IAHelper.mLocation != null) {
// tell the user they have arrived at their destination when within a certain distance from the destination point
Location current = new Location("Current Location");
current.setLatitude(IAHelper.mLocation.latitude);
current.setLongitude(IAHelper.mLocation.longitude);
Location destination = new Location("Destination");
destination.setLatitude(IAHelper.mDestination.latitude);
destination.setLongitude(IAHelper.mDestination.longitude);
float distanceBetween = current.distanceTo(destination);
Log.d(geoLocTag, "distanceBetween: " + distanceBetween);
isClose = distanceBetween < 6;
Log.d(geoLocTag, "isClose: " + isClose);
}
// check if a route to the destination currently exists
if(IAHelper.mCurrentRoute != null) {
createNavigationPath();
}
});
i have this problem too. when you find out a solution please notify me..
[email protected]
i use estimote ibeacons also for my project.
(my English is bad)!
@nbazos Have you got the way to render arrows?
Hi thanks for this request. Probably the best way to address it would be for us to write some sort of sample doing this. We don't have that currently, but we will track the request as we consider future samples.
@malik-at-work That couldn't be better! Thanks .
@malik-at-work Thank you, that sounds great!
Hi @malik-at-work any chance of getting a sample code for this? @nbazos were you able to get it working? Please let me know. Thanks
Hi @nbazos
I have the same problem, if you have completed this, could you show it to me?
Most helpful comment
i have this problem too. when you find out a solution please notify me..
[email protected]
i use estimote ibeacons also for my project.
(my English is bad)!