Viro: Location Based AR: Convert lat long to X,Y,Z coordinates in ViroReact

Created on 11 Jan 2018  ·  73Comments  ·  Source: viromedia/viro

Hi i was assuming if we can access the current location of Viro AR in terms of X and y coordinates to pin images?

Most helpful comment

Hi @mypark, @ashmanmalik, @amyramnauth,

I've attached code to demonstrate how to do this. I am no longer using the node js package I mentioned as @mypark brought up that package returns results in pixels that represent Google tiles.
I found other projection code here: https://gist.github.com/scaraveos/5409402 that I use to translate lat_long->mercator which is then translated into Viro AR Space.

To complete the transform into Viro AR, the object will have x= (longitude after merc projection - device position)and z=(latitude after merc projection - device position). I then flip the z axis as Viro has -Z facing north.

To align the compass in iOS you'll have to set worldAlignment="GravityAndHeading" in your ViroSceneARNavigator. This makes the x,z axis in Viro AR align to the north, south, east, west of your device compass. For android you'll need to take these final positions and rotate them around what north is using the compass of the device.

Finally for objects more than 60 meters away your object won't appear. This is due to a clipping bug that will be fixed in our next release next week.

Keep in mind, the code attached hard codes the device position as it's for example purposes only:
HelloWorldSceneAR.js.zip

BTW, given the potential inaccuracies of on device compasses it may be worthwhile asking the end user to calibrate their true north.

All 73 comments

Hi @ashmanmalik,
Can you describe your use case in more detail so we can get an idea of what you are trying to accomplish? Do you wish the user to tap on the screen and then pin images in the world based on that? Or are you looking for the latitude and longitude(GPS coords) that you can use to place and track images?

Here is a link describing how to place objects in AR using 3d coordinates: https://docs.viromedia.com/docs/augmented-reality-ar#section-camera-tracking

Hi @VikAdvani

I am trying to use GPS coordinates( latitude and longitude ) that i can use and track images with a distance from my current position to the targeted Image.

Let suppose, An image is place in the next street from your current place. When you enter to AR world. the camera would show an Point of interest on your screen in the direction of that GPS image coordinate.

If you need further explanation, Let me know..

Thanks

Hi @ashmanmalik,
Yes, this should be possible using React Viro as others have gotten something similar to work. It involves a bit of math.

You'll need to use this Geolocation module: https://facebook.github.io/react-native/docs/geolocation.html to get the lat/long points of the device.

Below are the steps to get this working:
1)To position the overlays, you have to convert your content from geographic coordinates(lat/long) into Viro AR space.

2)First project the spherical lat/long coordinates of your image into 2D projected coordinates.(ie lat/long to Web Mercator(a 2d projection).

3)Then translate the projected coordinates by the device's initial projected position. So you'd get the projected position of your device(current location lat/long transformed to 2d merc. projection) and the projected position of your image, subtract the two(first ensure 2d positions are in meters) to get the projected vector(distance from image to device) in projected mercator coordinates.

4)Now you need to the same with rotation.You need to convert from compass direction to device orientation in AR space. You'd then transform the final position from step #3 by this rotation to get the position in Viro AR Space. This can be better achieved by setting the worldAlignment parameter to "heading", so the AR coord system is aligned to the world, see this issue for more info on how to do this step: https://github.com/viromedia/viro/issues/118"

Let me know if that helps. Thanks!

Hi @VikAdvani

Can you explain more how can i convert the Geographic coordinates to VIRO AR space?

and how can i use Web Mercator in React?

Thanks

@dam00n Can you please help with this issue. I am trying to convert the Geographic coordinates to Viro AR space, I found a node mercator but unable to sort coordinates. Can you provide an example project for overlaying the images with Viro AR space?

Hi @ashmanmalik, we are working on getting an example of this in a future release.

But for now, you'd use a library like this: https://www.npmjs.com/package/mercator-projection

and do something like the following:

// translate image card to xy 
var imagePos = merc.fromLatLngToPoint({lat: -27.470127, lng: 153.0147027});

// translate current device position to a lat/lng 
var currentDevicePos = merc.fromLatLngPoint({lat:currentDeviceLat, lng:currentDeviceLong});

var imageFinalPosX = imagePos.x - currentDevicePos.x;
var imageFinalPosY = imagePos.y - currentDevicePos.y;

You now have the position in 2d coordinates in meters, which can map to the Viro AR Space and be put on the xz plane. Make sure you set the worldAlignment to 'GravityAndHeading' in ViroARSceneNavigator so that the AR Space aligns properly to the compass direction.

Since the position has to be in xyz, assuming that height is 1m

should we translate the xy position like so?

x = imageFinalPosX
y = 1
z = imageFinalPosY

also, I noticed that VikAdvani's code sample uses a mercator-projection library that returns distance in pixels, how do we translate that to meters... assuming that Viro is expecting xy in meters.

  1. ...subtract the two(first ensure 2d positions are in meters)
    How do I ensure this?

I'm trying to implement something similar to this issue: mapping a POI using just lat/long and distance from user current location.
When I use mercator-projection to convert current position, I get an object with x and y values.
I then convert the POI lat/long position and get another object with x and y values.
After subtracting the image position from current device position, I get an object
{x: 46.10795959722368, y: 55.79737086742074}
How do I go about mapping these coordinates in my world? @VikAdvani

also - to get this working for android, would we be able to translate this java code that is mentioned in this git issue for AR Core https://github.com/google-ar/arcore-android-sdk/issues/119 into javascript using Viro?

Hi @mypark, @ashmanmalik, @amyramnauth,

I've attached code to demonstrate how to do this. I am no longer using the node js package I mentioned as @mypark brought up that package returns results in pixels that represent Google tiles.
I found other projection code here: https://gist.github.com/scaraveos/5409402 that I use to translate lat_long->mercator which is then translated into Viro AR Space.

To complete the transform into Viro AR, the object will have x= (longitude after merc projection - device position)and z=(latitude after merc projection - device position). I then flip the z axis as Viro has -Z facing north.

To align the compass in iOS you'll have to set worldAlignment="GravityAndHeading" in your ViroSceneARNavigator. This makes the x,z axis in Viro AR align to the north, south, east, west of your device compass. For android you'll need to take these final positions and rotate them around what north is using the compass of the device.

Finally for objects more than 60 meters away your object won't appear. This is due to a clipping bug that will be fixed in our next release next week.

Keep in mind, the code attached hard codes the device position as it's for example purposes only:
HelloWorldSceneAR.js.zip

BTW, given the potential inaccuracies of on device compasses it may be worthwhile asking the end user to calibrate their true north.

On Android, for rotating the final positions. Would you rotate the positions by the device heading like so, or how?

let angle = heading
let newRotatedX = objFinalPosX * Math.cos(angle) - objFinalPosZ * Math.sin(angle)
let newRotatedZ = objFinalPosZ * Math.cos(angle) + objFinalPosX * Math.sin(angle)

Hi @niallfarrell91 yep that formula seems correct. Does that work for you?

Yeh its working good for me :) . I just had to make sure my heading was correct when setting up the scene

Hello, @VikAdvani
Do you mean that
Vector v

double lon_rad = (longi / 180.0 * Math.PI);
double lat_rad = (lati/ 180.0 * Math.PI);
double sm_a = 6378137.0;

    double vX = sm_a * lon_rad;
    double vY = sm_a * (Math.log((Math.sin(lat_rad) + 1) / Math.cos(lat_rad)));

    v.x = (float) (vX-deviceLon);
    v.y = (float) vY;
    v.z = -(float) (vY-deviceLat);

I used I converted to java(android)
but, v.y and v.z are too high

I can't understand what you mean. help..
could you tell me what i should do more?

and Hello @niallfarrell91

do you mean that Objs in AR are heading to device?
how to use code in java?
Thank you

VikAdvani put up a very helpfully code example. Did you check that out?

I got the device heading, using a custom module react-native-heading. This gets the direction which the device is facing in degrees(0 being North). Then I just rotated all my objects in the scene by this rotation

Thank you! its working for me.
I just had a mistake :(

Geolocation:

  1. npm install react-native-geolocation-service
  2. import Geolocation from 'react-native-geolocation-service'
  3. Write below code in componentDidMount()
  4. Watchposition is to trigger getting your location continously

Code:
Geolocation.watchPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
string: String(position.coords.latitude)
});
this.getCoordinate()
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 2000, maximumAge: 2000, distanceFilter: 1 },
)

Translate longitude and latitude --> XYZ (Viromedia location)

  1. npm install ecef-projector
  2. import projector from 'ecef-projector'
  3. follow code below, which will generate [x, y, z]

Code
const userxyz = projector.project(latitude, longitude, 0.0)

Get distance between two location

  1. Follow code below

getDistance = (lon1, lat1, lon2, lat2) => {
if (typeof(Number.prototype.toRad) === "undefined") {
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
}

var R = 6371; // Radius of the earth in km
var dLat = (lat2-lat1).toRad();  // Javascript functions in radians
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c * 1000 // Distance in km
return d.toFixed(2)

}

Hope it will help you @ashmanmalik

Hi all,

I tried using the example code from @devalensio, but I'm not able to get my current location...
what am I doing wrong? I'm trying to show the latitude and longitude in the ViroText component, just to check if the location is correct.

export default class HelloWorldSceneAR extends Component {

  constructor() {
    super();

    // Set initial state here
    this.state = {
      text: "Initializing AR...",
      latitude: "Initializing latitude",
      longitude: "Initializing longitude",
    };

    // bind 'this' to functions
    this._onInitialized = this._onInitialized.bind(this);
  }


  componentDidMount() {
    Geolocation.getCurrentPosition((position) => {
      this.setState({
        latitude: position.coords.latitude,
        longitude: position.coords.longitude,
        error: null,
        string: String(position.coords.latitude)
      });
    }, (error) => this.setState({error: error.message}),)
  }

  render() {

    return (<ViroARScene onTrackingUpdated={this._onInitialized}>
      <ViroText text={String(this.state.longitude)} scale={[.5, .5, .5]} position={[0, -2, -3]} style={styles.helloWorldTextStyle}/>
      <ViroText text={String(this.state.latitude)} scale={[.5, .5, .5]} position={[0, -1, -3]} style={styles.helloWorldTextStyle}/>
      <ViroText text={String(this.state.text)} scale={[.5, .5, .5]} position={[0, 0, -3]} style={styles.helloWorldTextStyle}/>
    </ViroARScene>);
  }

  _onInitialized(state, reason) {
    if (state == ViroConstants.TRACKING_NORMAL) {
      this.setState({
        text : "Hello World!"
      });
    } else if (state == ViroConstants.TRACKING_NONE) {
      // Handle loss of tracking
    }
  }
}

And I'm also getting a warning...
Can anyone please help me with this?
screenshot_20180520-213228_viro media2

Hi @AntoniaBe,
Are you developing using the Viro Testbed App or did you setup your project with XCode/Android? If you are using the Viro Media Testbed app, then this is why you are seeing the error. The Geolocation module is a native react module so you'll need to add it to your XCode or Android project and then build from there, since native modules aren't including with our testbed app.

If you don't add the module properly then you'll get the warning you see above.

Let me know if this helps!

Hi @VikAdvani

sorry for the late reply. I used the testbed app before, but now I managed to make a build on my phone with Android Studio. But I still have the same problem as mentioned in my last post...

Hi @AntoniaBe,
I'm assuming you are using the following npm react native package for geolocation: https://www.npmjs.com/package/react-native-geolocation-service

Did you add the proper dependencies to your build.gradle file and import the the proper files in your JS files as stated on the NPM page?

yes, I did everything according to this page but I'm still getting null as latitude and longitude values... :(

Okay I'm not quite sure what happened over night, but its working now 👍

Hi again,

I have a problem with rotating the final positions. I used @niallfarrell91 code example and the react-native-heading module from this repository https://github.com/zsajjad/react-native-heading, since the original one didn't work for me. But the text I am trying to place always has a different position...so I'm not quite sure what I am doing wrong.

  componentDidMount() {
...
...
  this.listener.addListener('headingUpdated', heading => {
          this.setState({headingAngle: heading});
    });
}

  _transformPointToAR(lat, long) {
...
...
    let angle = this.state.headingAngle;
    let newRotatedX = objFinalPosX * Math.cos(angle) - objFinalPosZ * Math.sin(angle)
    let newRotatedZ = objFinalPosZ * Math.cos(angle) + objFinalPosX * Math.sin(angle)

    return ({
      x:  newRotatedX,
      z: -newRotatedZ
    });
}

Is this correct or did I misunderstood something?

is there no one who can help me with this? :(

any help would be appreciated

Hi @AntoniaBe,
The code seems correct. If it is showing a different position every time I'd check if the headingAngle you are getting is the same or different every time you try it(assuming the device is oriented the same way). If it is different, it's prob due to the way the compass works on the device(most device compasses need to be calibrated). You'll prob want to the user to orient and calibrate the compass on the device themselves(ie. provide an affordance that allows them to orient the device till it's facing north) then take that heading angle and use it orient objects around you.

Let me know if that makes sense or if you need any more info!

Hi @VikAdvani

my headingAngle is the same when the device is oriented the same way, of course when I move it, it changes. So something must be wrong and I can't figure out what it is.

And I don't really understand how to make that affordance, could you maybe give me an example or explain this more in detail?

Hi @AntoniaBe,
If the angle is the same then the math will always give the same position which should lead the text to display at the same location. Are you seeing the text drift? It could be ARCore is not fully 'calibrated' and the text is trying to anchor.

I believe the issue is most likely related to the compass itself. Device based compasses can be distorted easily by even magnets in earphones. What I meant by affordance is that you can ask the user to point their device till it faces 'their north' before the navigation, then retrieve that value from the gyroscope and use it to rotate the points to orient them.

Another thing to check is if your angle from the react-native-heading is in radians as the JS Math libraries take radians and not angles. While this won't explain inconsistent values from the same angle, still worth checking to ensure you get the right values.

Hello guys, really a good discussion, i am also looking to develop similar apps so is it done finally or still in development phase? where can i see final working code ? any help will be appriciated

@Arvrairobo see @VikAdvani comment and attached file on March 30th

hello, i implemented @VikAdvani given code and my app works fine but the issue is the POI position changes while switching between the app or even if i go to home screen...what can be the problem?..any help will be appreciated

Hi @sjt145, this could be due to the compass on the device. The compass may be wildly inaccurate depending on where you are since its based on the magnetic field and that can be distorted by objects. One way to tell if it's the compass is to remove the compass rotations, and see if the positions appear the same.

If it is the compass, it's best to ask the user to calibrate the compass so they can help your app understand what 'north' it.

hello @VikAdvani thank you for replying...yes i did check with and without compass...the problem is at first when you start app it works fine with all proper position but going on and off the app points get distort...and if its due to compass then is there any other way i can align my point to one position without using compass...and other sensors provided in viro??? please help me out with this code i am new to React-Viro..

Hi @sjt145, unfortunately their aren't really any sensors that can help with this as it's a limitation of the hardware and the way the compass works on the phone. One thing I've seen people do, is ask the user to point to their true north themselves with their device, effectively a way for them to configure north themselves. Once you know what 'north' is, you can infer the other directions based on the gyroscope values of north.

This isn't ideal but a possible solution.

Hi, does anyone know how to set a distance limit to display AR object?

For example,
If the distance between AR object and device is within 200 meter, then AR object can be displayed.
Else AR object cannot be displayed.

Can somebody help pls?

Hi @HLneoh,

If you have 2 positions, [x0, y0, z0] and [x1, y1, z1], then the distance between the two are:

√( (x0 - x1)2 + (y0 - y1)2 + (z0 - z1)2)

You can grab the camera's position through ViroARScene's onCameraTransformUpdate which returns an object w/ the following info:

{
  position : [x, y, z],
  rotation : [x, y, z],
  forward : [x, y, z],
  up : [x, y, z]
}

Then compare the object's position to the camera's position and you can either use the visible prop available on most Viro components to show/hide your object or you can conditionally render the object by removing/adding it to the render() function.

@AntoniaBe Hi did you ever figure out your issue? I am experiencing the same thing where my heading is the same, but every time I reinitialize the scene it appears in a different location.

Ah I found the solution, for anyone else with this issue in the future.

The angle needs to be in Radians and not Degrees.

All i am going to close this issue. Thanks everyone for your help. Cheers

hello @seanyusa,
can you please share your code, as i am facing the same problem and my angles are already in radians.
Thank you,

What part of the code are you referring to? If you post your code I can just take a look.

On Jan 31, 2019, at 11:23 PM, sjt145 notifications@github.com wrote:

hello @seanyusa https://github.com/seanyusa,
can you please share your code, as i am facing the same problem and my angles are already in radians.
Thank you,


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/viromedia/viro/issues/131#issuecomment-459610018, or mute the thread https://github.com/notifications/unsubscribe-auth/AJ_n_1VQdrPH_f7gbSIApcOc24CZ_hJEks5vI89ggaJpZM4RaXx2.

hello @seanyusa here is my code,

'use strict';
import React, { Component } from 'react';
import {StyleSheet,NativeEventEmitter,DeviceEventEmitter,AsyncStorage,PermissionsAndroid} from 'react-native';
import ReactNativeHeading from '@zsajjad/react-native-heading';
import Geolocation from 'react-native-geolocation-service'
import {
  ViroARSceneNavigator,
  ViroARScene,
  ViroText,
  ViroConstants,
  ViroImage,
  ViroARPlane,
  ViroBox,  
} from 'react-viro';
import RNSimpleCompass from 'react-native-simple-compass';
const degree_update_rate = 3; // Number of degrees changed before the callback is triggered
export default class HelloWorldSceneAR extends Component {
  async requestLocationPermission() 
  {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
    )
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      //console.log("You can use the location")
      //alert("You can use the location");
      Geolocation.getCurrentPosition((Degree=this.state.Degree) => { //change to position if degree doesnt work
        this.setState({
          latitude: Degree.coords.latitude,
          longitude: Degree.coords.longitude,         
          error: null,
          string: String(Degree.coords.latitude)
        });
      }, (error) => this.setState({error: error.message}),
      { enableHighAccuracy: true}
      )
    } else {
      //console.log("location permission denied")
      alert("Location permission denied");
    }
    return granted;
  } catch (err) {
    console.warn(err)
  }
}
  constructor() {
    super();
   this.requestLocationPermission=this.requestLocationPermission.bind(this);
    // Set initial state here
    this.state = {
      text: "Initializing AR...",
      latitude: 0,
      longitude: 0,
      femalefirstX: 0,
      femalefirstZ: 0,
      appleX: 0,
      appleZ: 0,    
      civilX: 0,
      civilZ: 0,
      subjailX: 0,
      subjailZ: 0,
      dhirajX: 0,
      dhirajZ: 0,     
      headingAngle:0,
      headAngle:0
    };
    RNSimpleCompass.start(degree_update_rate, (degree) => {
      this.setState({Degree: degree});      
      RNSimpleCompass.stop();     
    });
    // bind 'this' to functions   
    this._onInitialized = this._onInitialized.bind(this);
    this._latLongToMerc = this._latLongToMerc.bind(this);   
    this._transformPointToAR = this._transformPointToAR.bind(this);   
  }
  updateHead(){    
    AsyncStorage.setItem('headstart',JSON.stringify( this.state.headingAngle))
  }  
  componentDidMount() {    
   this.requestLocationPermission();   
    ReactNativeHeading.start(1)
    .then(didStart => {
        this.setState({
            headingIsSupported: didStart,   })
    }) 
     var flag = 0
     DeviceEventEmitter.addListener('headingUpdated', heading => {
      this.setState({headingAngle:heading})
      //console.log('heading State',heading)
      if(flag == 0){
        this.updateHead()
      }
      flag = 1
    });    
    this.updateHead()
  }
  componentWillUnmount() {    
    ReactNativeHeading.stop();
    DeviceEventEmitter.removeAllListeners('headingUpdated');
  }
  render() {
    return (<ViroARScene onTrackingUpdated={this._onInitialized}>   
          <ViroText  text="female first hospital"  transformBehaviors={["billboard"]} scale={[0.2, 0.2, 0.2]}  position={[this.state.femalefirstX, 0, this.state.femalefirstZ]}  style={styles.helloWorldTextStyle} />
           <ViroText text="apple hospital" scale={[4, 4, 4]} transformBehaviors={["billboard"]}  position={[this.state.appleX, 0, this.state.appleZ]} style={styles.helloWorldTextStyle} />
           <ViroText text="civil hospital" scale={[4,4,4]} transformBehaviors={["billboard"]}  position={[this.state.civilX, 0, this.state.civilZ]} style={styles.helloWorldTextStyle} />
          <ViroText text="subjail" scale={[3, 3, 3]} transformBehaviors={["billboard"]}  position={[this.state.subjailX, 0, this.state.subjailZ]} style={styles.helloWorldTextStyle} />
          <ViroText text="dhiraj sons" scale={[5, 5, 5]} transformBehaviors={["billboard"]}  position={[this.state.dhirajX, 0, this.state.dhirajZ]} style={styles.helloWorldTextStyle} />
    </ViroARScene>);   
  }
   _onInitialized() {  
      var femalefirst = this._transformPointToAR(21.182531,72.826317);
      var apple = this._transformPointToAR(21.182657, 72.831573);
      var civil=this._transformPointToAR(21.179215, 72.821873);
      var subjail=this._transformPointToAR(21.181359, 72.826964);
      var dhiraj=this._transformPointToAR(21.149431, 72.782777);
    this.setState({
      femalefirstX: femalefirst.x,
      femalefirstZ: femalefirst.z,
      appleX: apple.x,
      appleZ: apple.z,      
      civilX:civil.x,
      civilZ:civil.z,
      subjailX:subjail.x,
      subjailZ:subjail.z,
      dhirajX:dhiraj.x,
      dhirajZ:dhiraj.z,      
      text : "AR Init called."
    });
  }
 _latLongToMerc(lat_deg, lon_deg) {
   var lon_rad = (lon_deg / 180.0 * Math.PI)
   var lat_rad = (lat_deg / 180.0 * Math.PI)
   var sm_a = 637813.70
   var xmeters  = sm_a * lon_rad
   var ymeters = sm_a * Math.log((Math.sin(lat_rad) + 1) / Math.cos(lat_rad))
   return ({x:xmeters, y:ymeters});
}
_transformPointToAR(lat, long) {
  AsyncStorage.getItem('headstart')
    .then(res=> {console.log('HeadAngle',res), this.setState({headAngle:res})} )
    var objPoint = this._latLongToMerc(lat, long);
    var devicePoint = this._latLongToMerc(this.state.latitude, this.state.longitude);
   // latitude(north,south) maps to the z axis in AR
  // longitude(east, west) maps to the x axis in AR
   var objFinalPosZ = (objPoint.y - devicePoint.y);
   var objFinalPosX = (objPoint.x - devicePoint.x);
  //flip the z, as negative z(is in front of us which is north, pos z is behind(south).
   return({x:objFinalPosX, z:-objFinalPosZ});
}
}
var styles = StyleSheet.create({
  helloWorldTextStyle: {    
    fontFamily: 'Arial',
    fontSize: 30,
    color: '#d30606',
    textAlignVertical: 'center',
    textAlign: 'center',
  },
});

module.exports = HelloWorldSceneAR; 

I hope this will help to find bug

Thank you

@sjt145 Looks like you are getting the heading (multiple times/ways for that fact). But are you using it anywhere in your calculations? I cannot see where you are using headingAngle or headAngle in your code.

You can refer to helpful code posted by those above:
https://github.com/viromedia/viro/issues/131#issuecomment-380521773
https://github.com/viromedia/viro/issues/131#issuecomment-393989648

@seanyusa yes i am getting headAngles but the problem is when i come to foreground from background in my application points get distort..how can i fix it at one position without distort....

@sjt145 I don't think there is anything you can do about that since it will always get disoriented when coming back to foreground. You'll need to re-initialize the AR view if you want to re-orient.

Hi @sjt145.
I've read your code and I think that I've found the bug.

_latLongToMerc(lat_deg, lon_deg) {
    var lon_rad = (lon_deg / 180.0 * Math.PI)
    var lat_rad = (lat_deg / 180.0 * Math.PI)
    var sm_a = 637813.70
    var xmeters = sm_a * lon_rad
    var ymeters = sm_a * Math.log((Math.sin(lat_rad) + 1) / Math.cos(lat_rad))
    return ({ x: xmeters, y: ymeters });
  }
  _transformPointToAR(lat, long) {
    var objPoint = this._latLongToMerc(lat, long);
    var devicePoint = this._latLongToMerc(this.state.latitude, this.state.longitude);

    objPointX = objPoint.x * cos(this.Degree) + objPoint.y * sen(this.Degree);
    objPointY = objPoint.y * cos(this.Degree) - objPoint.x * sen(this.Degree);

    var objFinalPosZ = (objPointY - devicePoint.y);
    var objFinalPosX = (objPointX - devicePoint.x);

    return ({ x: objFinalPosX, z: -objFinalPosZ });
  }

As you can see, you have to rotate de cartesian axis before you send the coordinates, this rotation is possible with the degrees that provide rnHeading.

I expect that can work properly.
A greeting.

hey @JulianGarzon22 ,
Thank you for code, I want to know here in this:

objPointX = objPoint.x * cos(this.Degree) + objPoint.y * sen(this.Degree);

what is 'this.Degree', is it the Degree I m getting from react native Heading??

Thanking you

hey @JulianGarzon22 ,
Thank you for code, I want to know here in this:

objPointX = objPoint.x * cos(this.Degree) + objPoint.y * sen(this.Degree);

what is 'this.Degree', is it the Degree I m getting from react native Heading??

Thanking you

Maybe little late, but:
@ashmanmalik i've a little project that you can use as an example.

https://github.com/mherrerabarraza/mapbox-viroreact-point-of-interes

Btw im using 'proj4' module to transform from LAT,LONG (Gps) to UTM (Cartesian).

@mherrerabarraza I was looking over your code and noticed that you don't consider where the user is facing/compass, is it needed?

@jalqueza It would be needed in Android. Since AR Core doesn't support built in heading.

@seanyusa I see so from my understanding iOS would consider where the user is facing, but in android the position has to be transformed in accordance the heading?

@jalqueza That's correct as long as you pass the GravityAndHeading option to the worldAlignment prop on iOS. https://docs.viromedia.com/v2.13.0/docs/viroarscenenavigator You'll find in the docs that the prop doesn't work on Android.

@seanyusa okay thanks I figured. On another note, do you know of another method of how to scale images? Right now I just multiply how far they the coordinate is by an arbitrary integer. Do you know of a more efficient solution?

@mherrerabarraza I was looking over your code and noticed that you don't consider where the user is facing/compass, is it needed?

@jalqueza
I did not even think about it, but it would be a good improvement. The big problem with my code is that I do not know how to put the polyline in a fixed position. For example, when I walk from one point to another along the line, I follow and lose the sense of the pathway. Any Idea?

@AntoniaBe Have you been able to fix the problem? I've got the same problem and using @niallfarrell91 's code to rotate the objects for Android (for iOS i am using worldAlignment={'GravityAndHeading'}). @VikAdvani can you help me out?

I'm using de magnetometer from react-native-sensors (https://github.com/react-native-sensors/react-native-sensors), but before using this im trying to get this working without real "compass" values. So i'm using constant values for now. See my code below.

createARObjectPosition = () => {
    const objPoint = this.latLongToMerc(latObj, longObj);
    const mobilePoint = this.latLongToMerc(latMobile, longMobile);

    const objDeltaY = objPoint.y - mobilePoint.y;
    const objDeltaX = objPoint.x - mobilePoint.x;

    const degree = 90; // for now i'm using a constant compass value (90 degree clockwise from north)
    const angleRadian = (degree * Math.PI) / 180; // degree to radian

    const newObjX = objDeltaX * Math.cos(angleRadian) - objDeltaY * Math.sin(angleRadian);
    const newObjY = objDeltaX * Math.sin(angleRadian) + objDeltaY * Math.cos(angleRadian);

    return { x: newObjX, y: 0, z: -newObjY }; // y is in my case always 0 (center of the screen).
    // for some reason this AR point is not valid? It jumps to different positions in AR space everytime i restart the AR app.
}
latLongToMerc = (latDeg: number, longDeg: number) => {
    // From: https://gist.github.com/scaraveos/5409402 
    const longRad = (longDeg / 180.0) * Math.PI;
    const latRad = (latDeg / 180.0) * Math.PI;
    const smA = 6378137.0;
    const xmeters = smA * longRad;
    const ymeters = smA * Math.log((Math.sin(latRad) + 1) / Math.cos(latRad));

    return { x: xmeters, y: ymeters };
  };

For some reason the calculated AR point seems to be not valid? It jumps to different positions in AR space everytime i restart the AR app. What am i doing wrong?

I've used the following link as example to compare and validate the calculated point results: https://keisan.casio.com/exec/system/1496886458

@jeffreyhaen i am facing similar problem, did u find a solution to your problem ?

Hi @jeffreyhaen, @SteponasIvasovas,

For some reason the calculated AR point seems to be not valid? It jumps to different positions in AR > space everytime i restart the AR app. What am i doing wrong

When you say it jumps to a different point every time you restart the app, I suspect what could be happening is that the 'GravityAndHeading' setting resets to calibrate the AR space with the device compass and the compass frankly isn't that accurate. Since your phone is likely in a different position, the AR space resets to what it thinks is true north, which is taken from the compass. However, the compass readings might be off.

To ensure this is happening you can:
1) Remove the 'GravityandHeading' setting for worldAlignment.
2) Start your app, look around to find your lat/long points.
3) Restart the app in a different position
4) Look around, the points should be in the same relative position to your start orientation.

If the above checks out, then it is a device compass issue. Other apps have solved this by asking the user to point to 'true north' via UX/UI and then using those values in conjunction with the compass to get a better orientation.

It's an unfortunate limitation of the current devices that the compass value can easily be distorted, esp in dense city areas.

Thanks for answering me @VikAdvani

To ensure this is happening you can:

  1. Remove the 'GravityandHeading' setting for worldAlignment.
  2. Start your app, look around to find your lat/long points.
  3. Restart the app in a different position
  4. Look around, the points should be in the same relative position to your start orientation.

If the above checks out, then it is a device compass issue. Other apps have solved this by asking the user to point to 'true north' via UX/UI and then using those values in conjunction with the compass to get a better orientation.

If i'm understanding the React Viro documentation correctly, the worldAlignment prop is not supported by ARCore on Android but iOS ARKit only. My app is working properly on iOS, i'm facing the issue on Android only.

I've followed your instructions anyways. I've removed worldAlignment and restarted my app in different positions. The points were in the same direction relative to my start position. But the whole point of my issue is that i want to rotate my objects according to the "true north" (based on the magnetometer). See code in my previous comment.

@SteponasIvasovas @CorentinOme @VikAdvani

i am facing similar problem, did u find a solution to your problem ?

I've not fixed my problem yet, but i've come close to a solution. The problem was that i was calculating the new object positions too early. The calculation happend when the AR triggered supported, but i had to wait until AR has been initialized (hence onTrackingUpdated triggers ViroConstants.TRACKING_NORMAL for the first time). After this code change my object positions are recalculated to the correct AR space positions. But for some reason my recalculation only works from 0 to 270. After 270 degree from north the positions are getting consistent incorrect again. I don't understand why.

From my scene component:

onTrackingUpdated = (state: any, reason: any) => {
    if (!this.state.hasARInitialized && state === ViroConstants.TRACKING_NORMAL) {
      this.setState(
        {
          hasARInitialized: true,
        },
        () => {
          this.props.onARInitialized();
        }
      );
    }
  };

Triggered when hasARInitialized is true:

transformGpsToAR = () => {
    const deviceObjPoint = this.latLongToMerc(latObj, longObj); // see previous post for code.
    const mobilePoint = this.latLongToMerc(latMobile, longMobile); // see previous post for code.

    const objDeltaY = deviceObjPoint.y - mobilePoint.y;
    const objDeltaX = deviceObjPoint.x - mobilePoint.x;

    if (isAndroid) {
      let degree = 90; // not using real compass yet.
      let angleRadian = (degree * Math.PI) / 180;

      console.log('Using degree => ', degree);
      console.log('Angle radian => ', angleRadian);

      let newObjX = objDeltaX * Math.cos(angleRadian) - objDeltaY * Math.sin(angleRadian);
      let newObjY = objDeltaX * Math.sin(angleRadian) + objDeltaY * Math.cos(angleRadian);

      console.log('old delta => ', { x: objDeltaX, z: -objDeltaY });
      console.log('new delta => ', { x: newObjX, z: -newObjY });

      return { x: newObjX, z: -newObjY };
    }

    return { x: objDeltaX, z: -objDeltaY };
  };

Closing due to inactivity.

Hi, i am also facing the same issue. position of viroImage is changing once restart the viro app from different direction

@karthickBabu93629 @jeffreyhaen can explain about the device compass degree? How do I get the compass degree using react native? can provide code snippet?

Fixed the issue, I used magnetometer and wrote my own custom logic and listeners to find the heading direction and its angle degree

Thats great, could you please share the code or send a PR request?

On Thursday, 30 April, 2020, 01:50:02 am IST, ManigandanRaamanathan <[email protected]> wrote:

Fixed the issue, I used magnetometer and wrote my own custom logic and listeners to find the heading direction and its angle degree


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.

hi @VikAdvani

I am facing this problem Convert lat long to X,Y,Z coordinates in ViroReact
actually, I want to do -
my object (Image ) is 200m from my current location.
I have done the above solution. After done the calculation between the current location to my object . AR show 5m around from my current location.
but it should be 200m from my location.
please help me
thanks

Hi,

I left this project 2 years ago, but i face the same problem. Since im
using a Free version of the GPS/Map is not so accurate. Maybe you can
follow the same logic, but with a better GPS service.

Cheers

El dom., 19 jul. 2020 a las 6:42, nishant2708 (notifications@github.com)
escribió:

hi @VikAdvani https://github.com/VikAdvani

I am facing this problem Convert lat long to X,Y,Z coordinates in ViroReact
actually, I want to do -
my object (Image ) is 200m from my current location.
I have done the above solution. After done the calculation between the
current location to my object . AR show 5m around from my current location.
but it should be 200m from my location.
please help me
thanks


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/viromedia/viro/issues/131#issuecomment-660624020, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AJQ3UC5ZG2UEA3Y7XCDHW63R4LE2LANCNFSM4ELJPR3A
.

--

Atentamente,
Manuel Herrera Barraza
+56 9 66451592

Restaurant La Ciudad Nueva
Casa Matriz Centro : Maipu #314, Telefono: +56 55 2388888 (Comida China)
Sucursal Sur 14 de Febrero #1945, Telefono: +56 9 82910663 (Comida
Tailandesa)}

Sucursal Norte: Los Chañares 291, Trocadero. Telefono: +56 55 2838888
(Comida China)

Antofagasta, Chile

You have to get a MAPBOX TOKEN like i mentioned in the Readme.md FIle:

https://github.com/mherrerabarraza/mapbox-viroreact-point-of-interes/blob/master/README.md

El lun., 20 jul. 2020 a las 2:36, nishant2708 (notifications@github.com)
escribió:

Hi @mherrerabarraza https://github.com/mherrerabarraza
please send the link of Free version of the GPS/Map.
thanks


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/viromedia/viro/issues/131#issuecomment-660833661, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AJQ3UC3QBHZW6EWE33OYIRDR4PQWTANCNFSM4ELJPR3A
.

--

Atentamente,
Manuel Herrera Barraza
+56 9 66451592

Restaurant La Ciudad Nueva
Casa Matriz Centro : Maipu #314, Telefono: +56 55 2388888 (Comida China)
Sucursal Sur 14 de Febrero #1945, Telefono: +56 9 82910663 (Comida
Tailandesa)}

Sucursal Norte: Los Chañares 291, Trocadero. Telefono: +56 55 2838888
(Comida China)

Antofagasta, Chile

thanks @mherrerabarraza

Your welcome!

El mar., 21 jul. 2020 a las 9:40, nishant2708 (notifications@github.com)
escribió:

thanks @mherrerabarraza https://github.com/mherrerabarraza


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/viromedia/viro/issues/131#issuecomment-661868194, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AJQ3UC6ZZXU4CLYSF42AXC3R4WLGPANCNFSM4ELJPR3A
.

--

Atentamente,
Manuel Herrera Barraza
+56 9 66451592

Restaurant La Ciudad Nueva
Casa Matriz Centro : Maipu #314, Telefono: +56 55 2388888 (Comida China)
Sucursal Sur 14 de Febrero #1945, Telefono: +56 9 82910663 (Comida
Tailandesa)}

Sucursal Norte: Los Chañares 291, Trocadero. Telefono: +56 55 2838888
(Comida China)

Antofagasta, Chile

Hi @mypark, @ashmanmalik, @amyramnauth,

I've attached code to demonstrate how to do this. I am no longer using the node js package I mentioned as @mypark brought up that package returns results in pixels that represent Google tiles.
I found other projection code here: https://gist.github.com/scaraveos/5409402 that I use to translate lat_long->mercator which is then translated into Viro AR Space.

To complete the transform into Viro AR, the object will have x= (longitude after merc projection - device position)and z=(latitude after merc projection - device position). I then flip the z axis as Viro has -Z facing north.

To align the compass in iOS you'll have to set worldAlignment="GravityAndHeading" in your ViroSceneARNavigator. This makes the x,z axis in Viro AR align to the north, south, east, west of your device compass. For android you'll need to take these final positions and rotate them around what north is using the compass of the device.

Finally for objects more than 60 meters away your object won't appear. This is due to a clipping bug that will be fixed in our next release next week.

Keep in mind, the code attached hard codes the device position as it's for example purposes only:
HelloWorldSceneAR.js.zip

BTW, given the potential inaccuracies of on device compasses it may be worthwhile asking the end user to calibrate their true north.

It worked for me

@SteponasIvasovas @CorentinOme @VikAdvani

i am facing similar problem, did u find a solution to your problem ?

I've not fixed my problem yet, but i've come close to a solution. The problem was that i was calculating the new object positions too early. The calculation happend when the AR triggered supported, but i had to wait until AR has been initialized (hence onTrackingUpdated triggers ViroConstants.TRACKING_NORMAL for the first time). After this code change my object positions are recalculated to the correct AR space positions. But for some reason my recalculation only works from 0 to 270. After 270 degree from north the positions are getting consistent incorrect again. I don't understand why.

From my scene component:

onTrackingUpdated = (state: any, reason: any) => {
    if (!this.state.hasARInitialized && state === ViroConstants.TRACKING_NORMAL) {
      this.setState(
        {
          hasARInitialized: true,
        },
        () => {
          this.props.onARInitialized();
        }
      );
    }
  };

Triggered when hasARInitialized is true:

transformGpsToAR = () => {
    const deviceObjPoint = this.latLongToMerc(latObj, longObj); // see previous post for code.
    const mobilePoint = this.latLongToMerc(latMobile, longMobile); // see previous post for code.

    const objDeltaY = deviceObjPoint.y - mobilePoint.y;
    const objDeltaX = deviceObjPoint.x - mobilePoint.x;

    if (isAndroid) {
      let degree = 90; // not using real compass yet.
      let angleRadian = (degree * Math.PI) / 180;

      console.log('Using degree => ', degree);
      console.log('Angle radian => ', angleRadian);

      let newObjX = objDeltaX * Math.cos(angleRadian) - objDeltaY * Math.sin(angleRadian);
      let newObjY = objDeltaX * Math.sin(angleRadian) + objDeltaY * Math.cos(angleRadian);

      console.log('old delta => ', { x: objDeltaX, z: -objDeltaY });
      console.log('new delta => ', { x: newObjX, z: -newObjY });

      return { x: newObjX, z: -newObjY };
    }

    return { x: objDeltaX, z: -objDeltaY };
  };

@jeffreyhaen Did you finish it on Android yet?

Was this page helpful?
0 / 5 - 0 ratings