AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

XE5 Orientation Sensor unter Android

Ein Thema von fcknbstrd · begonnen am 24. Okt 2013 · letzter Beitrag vom 28. Jul 2017
Antwort Antwort
fcknbstrd

Registriert seit: 24. Okt 2013
11 Beiträge
 
#1

XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 10:49
Hi,

ich spiele gerade mit der XE5 Delphi Demo herum.
Ich würde gern den Orientation-Sensor unter Android benutzen, um die Gyroscope und Compass Daten abzurufen.
Dabei nutze ich das Delphi-Beispiel unter:
http://sourceforge.net/p/radstudiode...ets/Gyroscope/

Führe ich die Anwendung auf meinem Smartphone aus (LG Optimus G E975, Android 4.1.2) aus, bekomme ich nur einmal Neigungswerte (Tilt),
die sich nicht weiter ändern, wenn ich das Smartphone drehe und wende.
Daraufhin habe ich die Beispiel-Anwendung nachgebaut und erweitert um den Status zu überprüfen. Alle nötigen Orientationsensoren (1x Compass3D und 1x Inclinometer3D) sind gestartet und auf "ready". Nun erhalte ich allerdings für die Neigungswerte immer 0 (obwohl TiltX, TiltY, TiltZ in AvailableProperties vorhanden ist). Die Heading-Werte des Kompass erhalte ich ganz normal.

Hab schon etliches durchprobiert: Auslesen des Sensors in einem eigenen Thread, mit einem Timer oder eventgesteuert (OnDataChanged). Mit verschiedenen Intervallen des Auslesen von 10ms - 1sek. Hab auch alle Rechte für Android angefordert.

Ich habe mir Beispiel-Apps aus dem PlayStore auf dem LG installiert, wo das Gyroscope vernünftig funktioniert. Würde also meinen, dass es nicht am Smartphone selbst liegt.

Hat jemand eine Idee was die Ursache für dieses Verhalten sein könnte?
Ist das ein Bug? Wird mein Smartphone von der Delphi-Bibliothek nicht sauber unterstützt?
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#2

AW: XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 11:32
Das Beispiel hat ja schon einige Schwachpunkte im Bezug auf Rückmeldungen im Fehlerfall.
Ich kommentiere mal den Sourcecode:
Delphi-Quellcode:
procedure TGyroscopeForm.Form3DCreate(Sender: TObject);
begin
  { attempt to get and activate the sensor manager }
  FSensorManager := TSensorManager.Current;
  FSensorManager.Activate;
  { attempt to get an orientation sensor }
  FSensors := TSensorManager.Current.GetSensorsByCategory(TSensorCategory.Orientation);
  if Length(FSensors) = 0 then
  begin
    Label1.Text := 'Gyro not found'; // gut, aber die Meldung sollte sein: "no sensors available"
    Exit; { no sensors available }
  end;
  if not (FSensors[0] is TCustomOrientationSensor) then
  begin
    // schlecht - hier fehlt die Rückmeldung an den User
    Label1.Text := 'no orientation sensor is available'; // neu hinzu
    Exit; { no orientation sensor is available }
  end;



  { start the sensor if it is not started }
  if not TCustomOrientationSensor(FSensors[0]).Started then
  begin
    TCustomOrientationSensor(FSensors[0]).Start;

    // sollte der Sensor aus irgendeinem Grund schon gestartet sein
    // dann wird der Timer nicht gestartet
    // die folgende Zeile sollte daher ausserhalb der if-Anweisung verschoben werden
    Timer1.Enabled := True;
  end
end;
fork me on Github
  Mit Zitat antworten Zitat
fcknbstrd

Registriert seit: 24. Okt 2013
11 Beiträge
 
#3

AW: XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 11:55
Zitat:
// sollte der Sensor aus irgendeinem Grund schon gestartet sein
// dann wird der Timer nicht gestartet
// die folgende Zeile sollte daher ausserhalb der if-Anweisung verschoben werden
Ist ein gutes Argument.
Mein Timer wird aber kontinuierlich ausgeführt, da ich mir einen Zähler ausgebe, der artig nach oben zählt.
  Mit Zitat antworten Zitat
fcknbstrd

Registriert seit: 24. Okt 2013
11 Beiträge
 
#4

AW: XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 13:25
Ich verstehe auch nicht, warum mir die offizielle Demo mir immerhin einmal Neigungswerte für den ersten Sensor (Compass3D) liefert, in meiner Testanwendung hingegen TiltX, TiltY und TiltZ für diesen nicht einmal definiert sind. Die Neigungswerte sind nur für den zweiten Sensor (Inclinometer3D) definiert, aber auf Null.

Ich habe mein Testprojekt mal angehangen.
Die Compiler-Direktive "USEGYROSCOPETHREAD" muss deaktiviert werden, wenn man den Abfrage per Timer aktivieren möchte.
Wäre super, wenn ihr mir sagen könntet, was ich falsch mache!?

Delphi-Quellcode:
unit uMain;

interface

uses
  System.SysUtils,
  System.Types,
  System.UITypes,
  System.Classes,
  System.Variants,
  FMX.Types,
  FMX.Controls,
  FMX.Forms3D,
  FMX.Forms,
  FMX.Dialogs,
  FMX.Sensors,
  FMX.Controls3D,
  FMX.Objects3D,
  System.Sensors,
  FMX.StdCtrls,
  FMX.Layers3D,
  FMX.MaterialSources,
  FMX.Layouts,
  FMX.Memo,
  FMX.ListBox
  {$IFDEF MSWINDOWS},
  ComObj,
  ActiveX,
  System.Win.Sensors,
  Winapi.Sensors,
  Winapi.Sensorsapi
  {$ENDIF};

{$IFnDEF MSWINDOWS}
  {$DEFINE USEGYROSCOPETHREAD}
{$ENDIF}

const
  SENSOR_INTERVAL = 100;

type
  TGyroscopeThread = class{$IFDEF USEGYROSCOPETHREAD}(TThread){$ENDIF}
    protected
      {$IFnDEF USEGYROSCOPETHREAD}
      fHandle : TTimer;
      {$ENDIF}

      fSensors : TSensorArray;
      fSensorManager : TSensorManager;
      fAvailable : Boolean;
      fIterations : Int64;
      fState : TSensorState;

      fRotation : Array[0..2] of Double;
      fDistance : Array[0..2] of Double;
      fHeading : Array[0..2] of Double;

      fMagHeading : Double;
      fTrueHeading : Double;
      fCompMagHeading : Double;
      fCompTrueHeading : Double;

      fMessage : String;

      {$IFDEF MSWINDOWS}
      fIntf : ISensor;
      {$ENDIF}

      procedure handleOrientationSensor(const ASensor : TCustomOrientationSensor);

      procedure SyncOutputMessage();
      procedure SyncCamera();

      procedure SynchronizeOutputMessage(const AMessage : String);

      procedure Execute(); {$IFDEF USEGYROSCOPETHREAD}override;{$ENDIF}
      {$IFnDEF USEGYROSCOPETHREAD}
      procedure doOnExecute(Sender : TObject);
      {$ENDIF}

    public
      property available : Boolean read fAvailable write fAvailable;

      constructor Create(); reintroduce; virtual;
      destructor Destroy; override;

      {$IFnDEF USEGYROSCOPETHREAD}
      procedure Start();
      procedure Terminate();
      {$ENDIF}
  end;

  TGyroscopeForm = class(TForm3D)
    LightMaterialSource1: TLightMaterialSource;
    Light1: TLight;
    Layer3D1: TLayer3D;
    Label1: TLabel;
    Cube1: TCube;
    Camera1: TCamera;
    Timer1: TTimer;
    Layer3D2: TLayer3D;
    Lbl_Iterations: TLabel;
    Memo1: TMemo;
    CkBx_Active: TCheckBox;
    procedure Form3DCreate(Sender: TObject);
    procedure Form3DDestroy(Sender: TObject);
    procedure CkBx_ActiveChange(Sender: TObject);
  private
    fGyroscope : TGyroscopeThread;
  public
    { Public declarations }
  end;

var
  GyroscopeForm: TGyroscopeForm;

implementation

{$R *.fmx}

function getOrientationSensorType(const ASensor : TCustomOrientationSensor) : String;
begin
  with ASensor do
  case SensorType of
    TOrientationSensorType.Compass1D : result := 'Compass1D';
    TOrientationSensorType.Compass2D : result := 'Compass2D';
    TOrientationSensorType.Compass3D : result := 'Compass3D';
    TOrientationSensorType.Inclinometer1D : result := 'Inclinometer1D';
    TOrientationSensorType.Inclinometer2D : result := 'Inclinometer2D';
    TOrientationSensorType.Inclinometer3D : result := 'Inclinometer3D';
    TOrientationSensorType.Distance1D : result := 'Distance1D';
    TOrientationSensorType.Distance2D : result := 'Distance2D';
    TOrientationSensorType.Distance3D : result := 'Distance3D';

    else result := 'Unknown';
  end;
end;




constructor TGyroscopeThread.Create();
var lSensor : TCustomSensor;
    lOrientationSensor : TCustomOrientationSensor;
    lSensorType : String;
begin
  inherited {$IFDEF USEGYROSCOPETHREAD}Create(true){$ENDIF};

  {$IFnDEF USEGYROSCOPETHREAD}
  fHandle := TTimer.Create(nil);
  with fHandle do
  begin
    OnTimer := doOnExecute;
    Interval := SENSOR_INTERVAL;
    Enabled := false;
  end;
  {$ELSE}
  FreeOnTerminate := true;
  {$ENDIF}

  fIterations := 0;

  fSensorManager := TSensorManager.Current;
  fSensorManager.Activate;

  fSensors := TSensorManager.Current.GetSensorsByCategory(TSensorCategory.Orientation);

  if (System.Length(fSensors) = 0) then
  begin
    SynchronizeOutputMessage('no sensors available');
    exit;
  end;

  if not (fSensors[0] is TCustomOrientationSensor) then
  begin
    SynchronizeOutputMessage('default orientation sensor not available');
    exit;
  end;

  for lSensor in fSensors do
  begin
    lOrientationSensor := lSensor as TCustomOrientationSensor;
    with lOrientationSensor do
    begin
      if not Started then
      begin
        Start();
        if not Started then
          raise Exception.Create('failed to start orientation sensor');

        lSensorType := getOrientationSensorType(lOrientationSensor);
        SynchronizeOutputMessage('Sensor started: ' + Name + ' (' + Model + '::' +
                                 SerialNo + ') - ' + lSensorType);
      end
      else
      begin
        lSensorType := getOrientationSensorType(lOrientationSensor);
        SynchronizeOutputMessage('Sensor already started: ' + Name + ' (' + Model + '::' +
                                 SerialNo + ') - ' + lSensorType);
      end;
    end;
  end;

  fAvailable := true;
end;

destructor TGyroscopeThread.Destroy;
var lSensor : TCustomSensor;
    lOrientationSensor : TCustomOrientationSensor;
    lSensorType : String;
begin
  for lSensor in fSensors do
  begin
    lOrientationSensor := lSensor as TCustomOrientationSensor;

    with lOrientationSensor do
    begin
      Stop();

      lSensorType := getOrientationSensorType(lOrientationSensor);
      SynchronizeOutputMessage('Sensor stopped: ' + Name + ' (' + Model + '::' +
                               SerialNo + ') - ' + lSensorType);
    end;
  end;

  fSensorManager.Deactivate;

  inherited;
end;

procedure TGyroscopeThread.SyncOutputMessage();
begin
  if (fMessage > '') then
  with GyroscopeForm do
  begin
    Memo1.Lines.Insert(0, fMessage);
    fMessage := '';
  end;
end;

procedure TGyroscopeThread.SyncCamera();
begin
  with GyroscopeForm do
  begin
    Label1.Text := Format('Rotation: %3.1f %3.1f %3.1f',
                          [fRotation[0],
                           fRotation[1],
                           fRotation[2]]);

    with GyroscopeForm.Camera.RotationAngle do
    begin
      X := fRotation[0];
      Y := fRotation[1];
      Z := fRotation[2];
    end;

    Lbl_Iterations.Text := 'Iterations: ' + IntToStr(fIterations);
  end;
end;

procedure TGyroscopeThread.SynchronizeOutputMessage(const AMessage : String);
begin
  fMessage := AMessage;
  {$IFDEF USEGYROSCOPETHREAD}
  Synchronize(SyncOutputMessage);
  {$ELSE}
  SyncOutputMessage();
  {$ENDIF}
end;

procedure TGyroscopeThread.handleOrientationSensor(const ASensor : TCustomOrientationSensor);
var lSensorType : String;

  function ready() : Boolean;
  var lMsg : String;
  begin
    case ASensor.State of
      TSensorState.Added : lMsg := 'sensor - added';
      TSensorState.Removed : lMsg := 'sensor - removed';
      TSensorState.Initializing : lMsg := 'sensor - initializing';
      TSensorState.Ready : begin
                                    result := true;
                                    exit;
                                  end;
      TSensorState.NoData : lMsg := 'sensor - no data';
      TSensorState.AccessDenied : lMsg := 'sensor - access denied';
      TSensorState.Error : lMsg := 'sensor error';
    end;

    SynchronizeOutputMessage(lSensorType + ': ' + lMsg);
    result := false;
  end;

begin
  inc(fIterations);

  with ASensor do
  begin
    lSensorType := getOrientationSensorType(ASensor);

    if ready() then
    begin
      if (TCustomOrientationSensor.TProperty.TiltX in AvailableProperties) then
      begin
        fRotation[0] := TiltX;
        fRotation[1] := TiltY;
        fRotation[2] := TiltZ;

        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('Rotation: %3.1f %3.1f %3.1f',
                                        [TiltX, TiltY, TiltZ]));
      end;

      if (TCustomOrientationSensor.TProperty.DistanceX in AvailableProperties) then
      begin
        fDistance[0] := DistanceX;
        fDistance[1] := DistanceY;
        fDistance[2] := DistanceZ;

        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('Distance: %3.1f %3.1f %3.1f',
                                        [DistanceX, DistanceY, DistanceZ]));
      end;

      if (TCustomOrientationSensor.TProperty.HeadingX in AvailableProperties) then
      begin
        fHeading[0] := HeadingX;
        fHeading[1] := HeadingY;
        fHeading[2] := HeadingZ;

        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('Heading: %3.1f %3.1f %3.1f',
                                        [HeadingX, HeadingY, HeadingZ]));
      end;

      if (TCustomOrientationSensor.TProperty.MagHeading in AvailableProperties) then
      begin
        fMagHeading := MagHeading;
        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('MagHeading: %3.1f',
                                        [MagHeading]));
      end;

      if (TCustomOrientationSensor.TProperty.TrueHeading in AvailableProperties) then
      begin
        fTrueHeading := TrueHeading;
        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('TrueHeading: %3.1f',
                                        [TrueHeading]));
      end;

      if (TCustomOrientationSensor.TProperty.CompMagHeading in AvailableProperties) then
      begin
        fCompMagHeading := CompMagHeading;
        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('CompMagHeading: %3.1f',
                                        [CompMagHeading]));
      end;

      if (TCustomOrientationSensor.TProperty.CompTrueHeading in AvailableProperties) then
      begin
        fCompTrueHeading := CompTrueHeading;
        SynchronizeOutputMessage(lSensorType + ': ' +
                                 Format('CompTrueHeading: %3.1f',
                                        [CompTrueHeading]));
      end;

      fState := State;
    end;
  end;
end;

procedure TGyroscopeThread.Execute();
var lSensor : TCustomSensor;
    lOrientationSensor : TCustomOrientationSensor;
begin
  {$IFDEF USEGYROSCOPETHREAD}
  while not terminated do
  begin
  {$ENDIF}

    // iterate through all orientation sensors
    if fAvailable then
    begin
      for lSensor in fSensors do
      begin
        lOrientationSensor := lSensor as TCustomOrientationSensor;
        handleOrientationSensor(lOrientationSensor);
      end;

  {$IFDEF USEGYROSCOPETHREAD}
      Synchronize(SyncCamera);
      sleep(SENSOR_INTERVAL);
    end;
  end;
  {$ELSE}
      SyncCamera();
    end;
  {$ENDIF}
end;

{$IFnDEF USEGYROSCOPETHREAD}
procedure TGyroscopeThread.doOnExecute(Sender : TObject);
begin
  execute();
end;

procedure TGyroscopeThread.Start();
begin
  fHandle.Enabled := true;
end;

procedure TGyroscopeThread.Terminate();
begin
  fHandle.Enabled := false;
end;
{$ENDIF}



procedure TGyroscopeForm.CkBx_ActiveChange(Sender: TObject);
begin
  fGyroscope.available := CkBx_Active.IsChecked;
end;

procedure TGyroscopeForm.Form3DCreate(Sender: TObject);
begin
  fGyroscope := TGyroscopeThread.Create();
  fGyroscope.Start();
end;

procedure TGyroscopeForm.Form3DDestroy(Sender: TObject);
begin
  fGyroscope.Terminate();
  {$IFnDEF USEGYROSCOPETHREAD}
  fGyroscope.Free();
  {$ENDIF}
end;

end.
Angehängte Dateien
Dateityp: zip GyroscopeTest.zip (10,2 KB, 34x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.406 Beiträge
 
Delphi XE8 Enterprise
 
#5

AW: XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 17:29
Was zeigt Dir den die Demo SensorInfo an ? Das Beispiel ließt alle Sensoren aus und gibt dazu die entsprechenden Werte zurück.
Rolf Warnecke
EasyNetSoft
  Mit Zitat antworten Zitat
fcknbstrd

Registriert seit: 24. Okt 2013
11 Beiträge
 
#6

AW: XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 18:33
Die Demo zeigt mir an, dass ich als Orientation Sensoren: Compass3D und Inclinometer3D habe. Für den Compass3D bekomme ich auch nur die Heading-Werte. Beim Inclinometer3D bekomme ich die Tilt-Werte die auch hier alle Null sind.
Der GravityAccelerometer3D, LinearAccelerometer3D und AmbientLight bleiben ebenfalls auf Null.

Ich vermute so langsam, dass das Auslesen bestimmter Sensoren speziell für mein Smartphone nicht richtig funktioniert.
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.406 Beiträge
 
Delphi XE8 Enterprise
 
#7

AW: XE5 Orientation Sensor unter Android

  Alt 24. Okt 2013, 18:56
Oder hast Du irgendwelche Dienste oder Optionen abgeschaltet, die für die Sensoren zuständig sind. Weil sage ich bei iOS, dass er meinen aktuellen Ort nicht verwenden darf, spielt meine Anzeige vom Locationsensor auch verrückt und zeigt auch keine entsprechenden Werte an. Ist nur so eine Vermutung, da ich in Android nicht so fit bin. Hier findest Du Android-Geräte, die mit den Beispielen getestet wurden.
Rolf Warnecke
EasyNetSoft
  Mit Zitat antworten Zitat
fcknbstrd

Registriert seit: 24. Okt 2013
11 Beiträge
 
#8

AW: XE5 Orientation Sensor unter Android

  Alt 25. Okt 2013, 11:52
Ich hab versucht alle Optionen zu aktivieren und geschaut ob irgendwelche Dienste fehlen. Selbst dann werden keine Neigungswerte ausgegeben.
Ich habe die Demo-App beim einem Freund auf dem Nexus 4 (Das offizielle Embarcadero Testgerät!) ausprobiert.
Bei ihm werden ebenfalls nur Nullwerte für die Neigung ausgegeben.

Hat jemand mal die Gyroscope/SensorInfo Demos unter Android ausprobiert?
Denn im Moment sieht es für mich nach einem Bug im Delphi aus.
  Mit Zitat antworten Zitat
fcknbstrd

Registriert seit: 24. Okt 2013
11 Beiträge
 
#9

AW: XE5 Orientation Sensor unter Android

  Alt 25. Okt 2013, 13:55
Es hat sich anscheinend wirklich als Bug entpuppt:

http://qc.embarcadero.com/wc/qcmain.aspx?d=119447
http://qc.embarcadero.com/wc/qcmain.aspx?d=119924

Andere Benutzer haben ähnliche Probleme mit den anderen Sensoren.
  Mit Zitat antworten Zitat
derseitzer

Registriert seit: 12. Okt 2016
235 Beiträge
 
Delphi 10 Seattle Professional
 
#10

AW: XE5 Orientation Sensor unter Android

  Alt 28. Jul 2017, 14:31
Gibt es schon Lösungen zu diesem Problem? Habe das gleiche Problem..
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 07:51 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf