Ausrichtung bzw. Richtung

D

DiscoveR

Neues Mitglied
0
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);


}

}
}
 
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.
 
  • Danke
Reaktionen: DiscoveR
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!
 
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?
 
  • Danke
Reaktionen: DiscoveR
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
 
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.
 
  • Danke
Reaktionen: DiscoveR
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?
 
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!
 
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?


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.
 
  • Danke
Reaktionen: DiscoveR
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);


}
 
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.
 
  • Danke
Reaktionen: DiscoveR
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);


}


}
}
 
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.
 
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!!!
 

Ähnliche Themen

S
Antworten
33
Aufrufe
2.665
Sempervivum
S
C
Antworten
3
Aufrufe
932
sportspirit
sportspirit
K
Antworten
1
Aufrufe
806
swa00
swa00
Zurück
Oben Unten