Hacer Compass apuntar siempre a un lugar específico en Xamarin Forms

Estoy tratando de implementar Compass siguiendo Xamarin. Esenciales: Compass para dirigirse a un punto específico. Por el bien de la implementación y la prueba, añadí SfCircularGauge que funciona bien con la misma lógica. Desde entonces, no quiero usar XF, así que lo intenté sin XF. Pero cuando trabaja sin XF, la flecha no apunta a la dirección correcta y la flecha apunta al Norte solamente. El cálculo y los puntos son idénticos, es todo acerca de la flecha no apunta a la dirección correcta. (Estoy probando en iOS, no lo comprobó en Android)

double current_latitude = 25.2618616; // changed on Appearing
double current_longitude = 55.3254198; // changed on Appearing
readonly double QiblaLatitude = 21.4224779; //remains --> pointing to this location
readonly double QiblaLongitude = 39.8251832; //remains --> pointing to this location
readonly SensorSpeed speed = SensorSpeed.UI;
public MainPage()
{
  InitializeComponent();
  Compass.ReadingChanged += Compass_ReadingChanged;
  if (!Compass.IsMonitoring) Compass.Start(speed);
}
void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
{
    circularGauge.RotateTo(360 - e.Reading.HeadingMagneticNorth); // this is XF
    compassImage.RotateTo(360 - e.Reading.HeadingMagneticNorth);
    ImageArrow.RotateTo(360 - e.Reading.HeadingMagneticNorth);
    PointToQibla();
}
private async void GetLocation()
{
   try
   {
      var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromMilliseconds(10));
      var location = await Geolocation.GetLocationAsync(request);
      current_latitude = location.Latitude;
      current_longitude = location.Longitude;
    }
    catch(Exception ex){System.Diagnostics.Debug.WriteLine(ex.Message);}
}
private double Mod(double a, double b)
{
   return a - b * Math.Floor(a / b);
}
void PointToQibla()
{
   double latt_from_radians = current_latitude * Math.PI / 180;
   double long_from_radians = current_longitude * Math.PI / 180;
   double latt_to_radians = QiblaLatitude * Math.PI / 180;
   double lang_to_radians = QiblaLongitude * Math.PI / 180;
   double bearing = Math.Atan2(Math.Sin(lang_to_radians - long_from_radians) * Math.Cos(latt_to_radians), (Math.Cos(latt_from_radians) * Math.Sin(latt_to_radians)) - (Math.Sin(latt_from_radians) * Math.Cos(latt_to_radians) * Math.Cos(lang_to_radians - long_from_radians)));
   bearing = Mod(bearing, 2 * Math.PI);
   double bearing_degree = bearing * 180 / Math.PI;
   //normal arrow and XF
   ImageArrow.Rotation = pointer1.Value = bearing_degree;
   // Labels to show value 
   lblG.Text = LabelInfo.Text = string.Format("Lat: {0} Long: {1} degree:{2}", current_latitude,current_longitude,bearing_degree.ToString());
}
protected override void OnAppearing()
{
    base.OnAppearing();
    GetLocation();
}

XAML (tanto XF como normal)


        
            
            
        
        
            
                
                    
                        
                            
                                
                                    
                                        
                                        
                                        
                                    
                                
                            
                        
                        
                            
                        
                        
                            
                        
                    
                
            
            
        
        
            
                
                    
                    
                
                
                
                
            
        
    

El problema es que la flecha no apunta a la dirección específica, pero permanece en el norte siempre. El proyecto también está disponible GitHub

iOS Screenshot

Pregunta hecha hace 3 años, 4 meses, 27 días - Por binarybuilder


3 Respuestas:

  • Resolví este misterio siguiendo Cómo obtener Qibla Dirección en Compass Windows Phone 8? . El código actualizado se parece a abajo;

    void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
            {
                try
                {
                    //Qibla lat and long
                    var qiblaLocation = new Location(QiblaLatitude, QiblaLongitude);
                    //current position
                    var position = new Location(current_latitude, current_longitude);
                    var res = DistanceCalculator.Bearing(position, qiblaLocation);
                    var TargetHeading = (360 - res) % 360;
    
                    var currentHeading = 360 - e.Reading.HeadingMagneticNorth;
                    Heading = currentHeading - TargetHeading;
                    
                    Info = string.Format("Lat: {0} Long: {1} degree:{2}", current_latitude, current_longitude, Heading);
    
                }catch(Exception ex){//log exception}
            }
    

    El proyecto completo está en GitHub

    Respondida el Dec 19, 2020 a las 22:15 - por algorithmadeptc6cb

    Votos positivos: 0 | Votos negativos: 0

  • El problema puede ser debido a la conversión de grados a radianes en la función PointToQibla. Parece que estás calculando el ángulo en radianes y luego convirtiéndolo de nuevo a grados antes de asignarlo a la rotación de la flecha. Podrías intentar asignar el ángulo en radianes directamente a la rotación de la flecha sin convertirlo de nuevo a grados.

    Aquí hay una posible modificación en la función PointToQibla para asignar el ángulo en radianes directamente a la rotación de la flecha:

    csharp
    void PointToQibla()
    {
       double latt_from_radians = current_latitude  Math.PI / 180;
       double long_from_radians = current_longitude  Math.PI / 180;
       double latt_to_radians = QiblaLatitude  Math.PI / 180;
       double lang_to_radians = QiblaLongitude  Math.PI / 180;
       double bearing = Math.Atan2(Math.Sin(lang_to_radians - long_from_radians)  Math.Cos(latt_to_radians), (Math.Cos(latt_from_radians)  Math.Sin(latt_to_radians)) - (Math.Sin(latt_from_radians)  Math.Cos(latt_to_radians)  Math.Cos(lang_to_radians - long_from_radians)));
       bearing = Mod(bearing, 2 * Math.PI);
    
       // Asignar el ángulo en radianes directamente a la rotación de la flecha
       ImageArrow.Rotation = pointer1.Value = bearing;
    
       // Labels para mostrar el valor
       lblG.Text = LabelInfo.Text = string.Format("Lat: {0} Long: {1} degree:{2}", current_latitude, current_longitude, bearing.ToString());
    }
    

    Intenta hacer esta modificación y verifica si resuelve el problema con la dirección de la flecha. ¡Espero que te sea de ayuda!

    Respondida el Dec 20, 2020 a las 22:16 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema en tu código es que estás usando HeadingMagneticNorth en lugar de HeadingTrueNorth para calcular la dirección de la Qibla. HeadingMagneticNorth tiene en cuenta la declinación magnética, que es la diferencia entre el norte magnético y el norte verdadero. Esto puede causar errores en las lecturas de la brújula, especialmente cerca de los polos magnéticos.

    Para apuntar la brújula a una ubicación específica, debes utilizar HeadingTrueNorth. Aquí tienes el código corregido:

    csharp
    void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
    {
        circularGauge.RotateTo(360 - e.Reading.HeadingTrueNorth); // this is XF
        compassImage.RotateTo(360 - e.Reading.HeadingTrueNorth);
        ImageArrow.RotateTo(360 - e.Reading.HeadingTrueNorth);
        PointToQibla();
    }
    

    Además, debes asegurarte de que el dispositivo esté calibrado correctamente. La calibración se puede realizar en la configuración del dispositivo o mediante una aplicación de calibración de brújula.

    Una vez que hayas realizado estos cambios, la brújula debería apuntar correctamente a la ubicación específica.

    Respondida el Dec 20, 2020 a las 22:25 - por Gemini

    Votos positivos: 0 | Votos negativos: 0