1. Nimm jetzt an unserem 2. ADVENT-Gewinnspiel teil - Alle Informationen findest Du hier!

Ausrichtung bzw. Richtung

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von DiscoveR, 27.08.2011.

  1. DiscoveR, 27.08.2011 #1
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Hallo Leute,

    stecke gerade ein bisschen fest mit meiner App! Funktion soll sein das ein Kompass (ausgehend von der aktuellen Position) sich nach einem Ziel ausrichtet bzw. eben die Nadel auf das Zeil zeigt. Es ist kein Kompass mit Himmelsrichtungen sondern ohne (sodass ich den Kompass selbst nicht drehen muss) aber ich will die Nadel auf das Ziel ausrichten.

    Einen normalen kompass hab ich schon hinbekommen(der sich auch aktiv mitdreht) aber eben nicht die ausrichtung auf das Ziel.
    Die Daten des Ziels sind Location-Objekte welches latitude und longitude besitzt. Kann mir jemand helfen.


    Danke für eure Hilfe!
    Anbei der Code:

    // Aus Klasse DiscoveR wird statische Variable test durch folgender aufruf //verwendet: test = currentLocation.bearingTo(targetLocation)
    // currentLocation ist aktuelle position und targetLocation das Ziel


    package de.medieninformatik.discover;

    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Matrix;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.location.Location;
    import android.os.Bundle;
    import android.widget.ImageView;

    public class Compass extends Activity implements SensorEventListener{

    SensorManager sensorManager;
    Sensor sensor;
    ImageView needleView;
    Bitmap compassBitMap;
    Bitmap needleBitMap;

    Matrix matrix;




    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.compasslayout);

    sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);

    needleView = (ImageView) findViewById(R.id.needle);

    needleBitMap = BitmapFactory.decodeResource(getResources(), R.drawable.star);
    matrix = new Matrix();


    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {

    if(event.sensor == sensor){

    int winkel = (int) event.values[0];
    //Prüfen, ob Winkel größer oder kleiner als 180 Grad
    int swinkel = -winkel+(winkel>180? 360: 0);

    matrix.setRotate(DiscoveR.test);

    compassBitMap = Bitmap.createBitmap(needleBitMap, 0, 0, needleBitMap.getWidth(), needleBitMap.getHeight(), matrix, true);
    needleView.setImageBitmap(compassBitMap);


    }

    }
    }
     
  2. FelixL, 28.08.2011 #2
    FelixL

    FelixL Ehrenmitglied

    Beiträge:
    4,855
    Erhaltene Danke:
    754
    Registriert seit:
    26.11.2009
    Phone:
    Wileyfox Swift, HTC One M8
    Okay, das ganze ist für mich etwas undurchsichtig, aber ich denke du hast einen Denkfehler drin.


    bearingTo() liefert dir einen Winkel von Nord aus gesehen rechtsrum drehend. Sagen wir also du bist in Frankfurt am Main und willst nach Berlin, und behaupten mal das wären genau 50° Winkel von Nord aus gesehen. Jetzt zeigt dein Handy gerade genau nach Osten. Das fängst du ja sogar in onSensorChanged ab. Den Winkel (wenn das Gerät nach Osten schaut 90°) benutzt du dann aber lustigerweise nicht weiter ;)
    Du brauchst getbearing-swinkel.
     
    DiscoveR bedankt sich.
  3. DiscoveR, 29.08.2011 #3
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Hallo,
    danke für deine Antwort. Sorry das es so verwirrend war :) aber ich war schon echt am Ende ^^ .

    Du hast das schon richtig verstanden. Ursprünglich wurde dem Aufruf matrix.setRotate(....); auch swinkel als Pamarameter übergeben also matrix.setRotate(swinkel); aber dann ist es ja nur ein "normaler" Kompass der immer nach norden zeigt aber ich will so zu sagen einen eigenen Norden definieren bzw. will dass sich die Nadel nach einem Ziel ausrichtet .
    Von diesem Ziel habe ich die Längen und Breitengrade und habe daraus eine Location gemacht und wollte mit der bearingTo() den Winkel zu dieser Location rausbekommen - diesen vermeindlichen Winkel habe ich in der Variablen test gspeichert und dann der setRotate(test); übergeben.

    Vielleicht könntest du mir helfen wie ich der Nadel sage dass sie sich nach dem Ziel ausrichten soll bzw. manuell den Norden festlegen kann:)

    Vielen Dank!
     
  4. FelixL, 29.08.2011 #4
    FelixL

    FelixL Ehrenmitglied

    Beiträge:
    4,855
    Erhaltene Danke:
    754
    Registriert seit:
    26.11.2009
    Phone:
    Wileyfox Swift, HTC One M8
    Und ich wette deine Nadel zeigt durchgehend den selben Winkel an, egal wohin du das Gerät drehst. Kannst ja testweise mal ein genau nördliches oder südliches Ziel nehmen, ob die Nadel dann genau nach oben oder unten zeigt.


    matrix.setRotate(DiscoveR.test-swinkel);
    könnte schon reichen.
    Erklärung siehe oben. Du erhältst zwar vom Gerät die Info wie weit das Gerät vom Norden aus gedreht ist (swinkel) und die Info in welche Richtung es genau gedreht sein soll damit es aufs Ziel zeigt (getBearing), verknüpfst die dann aber nicht. logischerweise musst du beide benutzen.
    Musst vielleicht nochmal schauen wegen negativen Werten, wie du es obendrüber auch gemacht hast.


    Edit: Wenn das nicht funktioniert, kannst du den restlichen Sourcecode auch nochmal posten damit ich das nachbauen kann?
     
    DiscoveR bedankt sich.
  5. DiscoveR, 29.08.2011 #5
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Danke!

    Prinzipiell haben wir 2 Klassen : 1)DiscoveR und 2) Compass

    Das Problem ist das das Programm schon bei dem Aufrauf aus der Klasse DiscoveR:



    startButton.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {

    targetLocation.setLatitude(12.0);
    targetLocation.setLongitude(49.0);



    test = currentLocation.bearingTo(targetLocation);



    Intent i = new Intent(DiscoveR.this, Compass.class);
    startActivity(i);

    }
    });

    also wenn ich die testlocation einfach mal willkührlich setzte und dann dazu bearing berechne stürzt es ab ! Ist die Einheit falsch muss ich das Umwandeln ?

    Die aktuelle Position ermitteln wir über GPS mit dem Methodenaufruf (etc.) locationManager.getLastKnownLocation(provider) + requestLocationUpdates(...) und mit allen dazugehörigen Methoden.

    Danke für die Hilfe . Könnte es dir schon schicken aber es ist viel und will deine hilfe auch nicht ausnützen ! GlG
     
  6. FelixL, 29.08.2011 #6
    FelixL

    FelixL Ehrenmitglied

    Beiträge:
    4,855
    Erhaltene Danke:
    754
    Registriert seit:
    26.11.2009
    Phone:
    Wileyfox Swift, HTC One M8
    Ach so, es stürzt ab? Ich dachte es richtet sich nur nicht aus ;)
    In diesem Fall hilft erst mal Logcat.
    Entweder im Terminal adb logcat, oder in Eclipse (bei mir auf Englisch):
    Window-->Show View--> Other-->Android-->LogCat


    Dabei muss entweder der Emulator an sein oder das Gerät über USB an den PC angeschlossen sein (was es ja wahrscheinlich sowieso schon ist). Außerdem natürlich USB-debugging aktiviert (was genauso wahrscheinlich sowieso schon aktiviert ist ;)).
    Dann einmal den Fehler auslösen (hier durch App-Aufruf), und es erscheint eine meistens ziemlich klare Aussage was nicht passt.
     
    DiscoveR bedankt sich.
  7. DiscoveR, 29.08.2011 #7
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Also hab die targetLocation belegt um damit zu arbeiten . jetzt stürtzt es zumindest nicht mehr ab! :) Teilerfolg! ;-)

    targetLocation = new Location(LocationManager.GPS_PROVIDER);
    startButton.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
    Log.d(TAG, "Im klick Listener");

    targetLocation.setLatitude(49.0072919);
    targetLocation.setLongitude(12.1192548);

    Log.d(TAG, "Zielposition gesetzt ?");

    test = currentLocation.bearingTo(targetLocation);
    Log.d(TAG, "Bearing berechnet");


    Intent i = new Intent(DiscoveR.this, Compass.class);
    startActivity(i);

    }
    });

    Ok dann´habe ich das was due eben gesagt hast eingearbeitet :


    public void onSensorChanged(SensorEvent event) {

    if(event.sensor == sensor){

    int winkel = (int) event.values[0];
    //Prüfen, ob Winkel größer oder kleiner als 180 Grad
    int swinkel = -winkel+(winkel>180? 360: 0);

    matrix.setRotate(DiscoveR.test-swinkel);

    compassBitMap = Bitmap.createBitmap(needleBitMap, 0, 0, needleBitMap.getWidth(), needleBitMap.getHeight(), matrix, true);
    needleView.setImageBitmap(compassBitMap);


    }
    Jetzt funktioniert es aber immer noch nicht ganz : die Nadel ruckelt so und zeigt es nicht richtig an ... also als ich das smartphone gedreht habe ging es mal kurzzeitg :-( kann das an dem Bild für die Nadel liegen bzw. an dessen Größe?
     
  8. DiscoveR, 29.08.2011 #8
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Hallo habs jetzt hinbekommen: Fehler waren:

    1) Die größe der Kompass Nadel (einfach zu groß)

    2)matrix.reset(); hilft alles schneller zu machen : hab sie in der onSensorChanded(..) eingebaut!

    Danke nochmal!
     
  9. FelixL, 29.08.2011 #9
    FelixL

    FelixL Ehrenmitglied

    Beiträge:
    4,855
    Erhaltene Danke:
    754
    Registriert seit:
    26.11.2009
    Phone:
    Wileyfox Swift, HTC One M8

    Könnte auch daran liegen das du z.B. die Matrix auf 45° gedreht hast, jetzt willst du sie auf 46° drehen, und drehst sie dabei nochmal um 46° statt um 1°. Bin mir aber nicht sicher wie das Matrix.rotate funktioniert. Das würde aber erklären warum matrix.reset funktioniert hat, dann würdest du nämlich wieder bei 0° beginnen.
     
    DiscoveR bedankt sich.
  10. DiscoveR, 29.08.2011 #10
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Ok jetzt haben wir es getestet - draußen ! Also bis zu einem bestimmten Grad stimmt es aber dann schlägt es genau ins Gegenteil! Weiß nicht wie die Rechnung genau aussehen muss wegen des Bearing-Wertes ! Wird dieser in Abhängigkeit zum Norden Berechnet oder nicht?

    Hab mir gedacht dass es in Abhängigkeit von bearingTo (test) zu berechnen ist also, ob bearingTo() ( bezw. die Variable test) positiv oder negativ ist aber irgendwas scheint da nicht zu stimmen ! Kannst du mir da nochmal helfen!


    @Override
    public void onSensorChanged(SensorEvent event) {



    if(event.sensor.getType() == sensor.TYPE_ORIENTATION){





    int winkel = (int) event.values[0];
    //Prüfen, ob Winkel größer oder kleiner als 180 Grad
    int swinkel = -winkel+(winkel>180? 360: 0);



    if(DiscoveR.test >0){
    matrix.reset();
    matrix.setRotate(DiscoveR.test+swinkel);
    }

    else{
    matrix.reset();
    matrix.setRotate(DiscoveR.test-swinkel);

    }
    compassBitMap = Bitmap.createBitmap(needleBitMap, 0, 0, needleBitMap.getWidth(), needleBitMap.getHeight(), matrix, true);
    needleView.setImageBitmap(compassBitMap);


    }
     
  11. FelixL, 29.08.2011 #11
    FelixL

    FelixL Ehrenmitglied

    Beiträge:
    4,855
    Erhaltene Danke:
    754
    Registriert seit:
    26.11.2009
    Phone:
    Wileyfox Swift, HTC One M8
    Mach mit Log.e("MeinAppName", swinkel); und Log.e("MeinAppName", DiscoveR.test); im onSensorChanged eine Ausgabe des Winkels in die Logcat, und rechne von Hand. Dann bekommst du raus in welchen Bereichen du was addieren musst damit es passt.


    Edit: Oder Mach einfach eine Ausgabe in einen TextView oder so.
     
    DiscoveR bedankt sich.
  12. DiscoveR, 30.08.2011 #12
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Hallo FelixL,


    kannst du mir nochmal helfen! Möchte die bearingTo() also den winkel von Nord zum Ziel immer wieder aktualisieren - eben auch wenn ich den Standpunkt wechsele aber wenn ich Sensor und Location in der Klasse habe geht nichts!

    package de.medieninformatik.discover;

    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Matrix;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.ImageView;
    import android.widget.TextView;

    public class Compass extends Activity implements SensorEventListener{

    SensorManager sensorManager;
    Sensor sensor;
    ImageView needleView;
    Bitmap compassBitMap;
    Bitmap needleBitMap;
    Matrix matrix;
    //TextView ausgabeText;

    static LocationManager locationManager;
    LocationListener mylocationListener;
    Location currentLocation;
    String provider;
    Location targetLocation;
    float test;


    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.compasslayout);


    // ausgabeText = (TextView)findViewById(R.id.compassTextView);

    sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);

    needleView = (ImageView) findViewById(R.id.needle);

    needleBitMap = BitmapFactory.decodeResource(getResources(), R.drawable.nadelohne);
    //needleBitMap = BitmapFactory.decodeResource(getResources(), R.drawable.nadel1);
    matrix = new Matrix();


    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    provider = LocationManager.GPS_PROVIDER;
    targetLocation = new Location(provider);
    targetLocation.setLatitude(49.0072919);
    targetLocation.setLongitude(12.1192548);
    currentLocation = locationManager.getLastKnownLocation(provider);
    locationManager.requestLocationUpdates(provider, 500, 5, mylocationListener);
    mylocationListener = new LocationListener() {

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    // TODO Auto-generated method stub

    }

    @Override
    public void onProviderEnabled(String provider) {
    // TODO Auto-generated method stub

    }

    @Override
    public void onProviderDisabled(String provider) {
    // TODO Auto-generated method stub

    }

    @Override
    public void onLocationChanged(Location location) {
    if(location != null){

    currentLocation = location;

    }
    }};


    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {



    if(event.sensor.getType() == Sensor.TYPE_ORIENTATION){

    // test = currentLocation.bearingTo(targetLocation);





    int winkel = (int) event.values[0];
    //Prüfen, ob Winkel größer oder kleiner als 180 Grad
    int swinkel = -winkel+(winkel>180? 360: 0);

    //ausgabeText.setText("Sensorwinkel: "+swinkel+"\n"+"Winkel: "+winkel+"\n"+"Bearing: "+DiscoveR.test);

    if(test >= 0){
    matrix.reset();
    matrix.setRotate(DiscoveR.test+swinkel);
    }

    else{
    matrix.reset();
    matrix.setRotate(DiscoveR.test-swinkel);

    }
    compassBitMap = Bitmap.createBitmap(needleBitMap, 0, 0, needleBitMap.getWidth(), needleBitMap.getHeight(), matrix, true);
    needleView.setImageBitmap(compassBitMap);


    }


    }
    }
     
  13. FelixL, 30.08.2011 #13
    FelixL

    FelixL Ehrenmitglied

    Beiträge:
    4,855
    Erhaltene Danke:
    754
    Registriert seit:
    26.11.2009
    Phone:
    Wileyfox Swift, HTC One M8
    Entweder du musst mit mehreren Threads arbeiten oder sowohl den SensorEventListener als auch den LocationListener implementieren:
    public class Compass extends Activity implements SensorEventListener implements LocationListener ...


    locationManager.requestLocationUpdates(provider, 500, 5, this);


    oder so ähnlich.


    Dann kannst du noch das neuberechnen der Matrix und das Drehen der Grafik in eine eigene Funktion auslagern, falls du ein bisschen Code sparen willst.
     
  14. DiscoveR, 31.08.2011 #14
    DiscoveR

    DiscoveR Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    0
    Registriert seit:
    27.08.2011
    Haben es jetzt rausgefunden: Es lang an Eclipse - wenn man es kopiert und anpasst funktioniert es nicht - nur wenn man es alles selbst eintippt geht es ! :) Auch wenn man genau das Gleiche darstehen hat !

    Wirklich vielen Dank für die Hilfe!!!
     

Diese Seite empfehlen