1

コードは、モーションとジャイロの更新を取得し、それぞれ配列に入れ、キャプチャ イベントが発生した場合に配列内の最大値を選択するように機能しています。デバイスの動きの更新が .02 または .03 に設定されている場合、すべてが機能します。ただし、アプリケーションに必要な更新が .01 に設定されている場合、追加の出力/値を取得しています。ヘルプやガイダンスをいただければ幸いです。前もって感謝します。コードは次のとおりです。

#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>

#define kRadToDeg   57.2957795

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *pitchLabel;
@property (nonatomic, strong) CMMotionManager *motionManager;
@property (weak, nonatomic) IBOutlet UILabel *rotationXLabel;
@property (nonatomic, strong) CMDeviceMotion *motion;
@property (nonatomic, strong) NSMutableArray *pitchArray;
@property (nonatomic, strong) NSMutableArray *rotationArray;
@property (nonatomic) id maxRotation;
@property (nonatomic) id maxPitch;
@property BOOL captureValues;

@end

@implementation ViewController

- (CMMotionManager *)motionManager
{
    if (!_motionManager) {
    _motionManager = [CMMotionManager new];
    [_motionManager setDeviceMotionUpdateInterval:(.01)];
    [_motionManager setGyroUpdateInterval:(.01)];
}
return _motionManager;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self placePitchValuesInArray];
[self placeRotationValuesInArray];
}

-(void)placePitchValuesInArray {

NSMutableArray *pitchArray = [NSMutableArray array];
pitchArray = [[NSMutableArray  alloc] initWithCapacity:150];

if (_captureValues == NO) {

[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue              currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {

 self.pitchLabel.text = [NSString stringWithFormat:@"%.2gº", motion.attitude.pitch * kRadToDeg];

[pitchArray addObject:[NSString stringWithFormat:@"%.2gº", motion.attitude.pitch *  kRadToDeg]];

        _pitchArray = pitchArray;

        if (pitchArray.count >= 150) {  //maintain running array of 150 pitch values

        [pitchArray removeObjectAtIndex:0];
        }
        id maxPitch = [_rotationArray valueForKeyPath:@"@max.intValue"];

        _maxPitch = maxPitch;

         [self checkCapture];

         }];

         }
      }

-(void)placeRotationValuesInArray {

NSMutableArray *rotationArray = [NSMutableArray array];

rotationArray = [[NSMutableArray  alloc] initWithCapacity:150 ];

if (self.captureValues == NO) {

    [self.motionManager startGyroUpdatesToQueue:[NSOperationQueue currentQueue]  withHandler:^(CMGyroData *gyroData, NSError *error) {

        self.rotationXLabel.text = [NSString stringWithFormat:@"%f",  gyroData.rotationRate.x];

        [rotationArray addObject:[NSString stringWithFormat:@"%f", gyroData.rotationRate.x]];

        _rotationArray = rotationArray;

        if (rotationArray.count >= 150) { //maintain running array of 150 rotaion  values

            [rotationArray removeObjectAtIndex:0];
        }

        id maxRotation = [rotationArray valueForKeyPath:@"@max.intValue"];

        _maxRotation = maxRotation;

        [self checkCapture];
        }];

       }
   }

 -(void)checkCapture {

//to generate capture. iPhone is landscape with HOME button on RIGHT. Tilt left side     UP slightly. ROTATE quickly in a counter-clockwise fashion.

if (([self.pitchLabel.text integerValue] > 3) && ([self.rotationXLabel.text   integerValue] > 5))
{
    (_captureValues = YES);
    [_motionManager stopDeviceMotionUpdates];
    [_motionManager stopGyroUpdates];

    for (int i=0; i<30; i++){ // modify pitchArray to remove last 30 values
        [self.pitchArray removeLastObject];

    }

    id maxPitch = [_pitchArray valueForKeyPath:@"@max.integerValue"];

    _maxPitch = maxPitch;

   [self outputValues];
}

}

-(void)outputValues {

NSLog(@"Max Pitch Value from modified array = %@", _maxPitch);
NSLog(@"Max Rotation Value = %@", _maxRotation);
sleep(2.5);
[self resetFlagAndArrays];

}
-(void)resetFlagAndArrays {

(_captureValues = NO);
[_pitchArray removeAllObjects];
[_rotationArray removeAllObjects];
[self viewDidLoad];

 }

 @end

`

4

1 に答える 1

0

同様の問題を抱えている人のために解決策を共有したかっただけです。上記の checkCapture メソッドでデバイス モーションの更新を停止した後、遅延を追加し、「for ループ」を別のメソッドに移動しました。次のようにします。

[self performSelector:@selector(adjustValues) withObject:nil afterDelay:.5];

-(void)adjustValues {
 for (int i=0; i<30; i++){ // modify pitchArray to remove last 30 values
    [self.pitchArray removeLastObject];

 }

 id maxPitch = [_pitchArray valueForKeyPath:@"@max.integerValue"];

 _maxPitch = maxPitch;

 [self outputValues];
 }

これにより、更新間隔が 0.01 に設定されている場合、デバイス モーションの更新がコードの実行よりも速く発生しているように見えるため、データが「漏れる」という問題が解決されます。

于 2014-08-25T19:32:00.380 に答える