Я думаю, что двойная интеграция, вероятно, усложняет ситуацию. Если я правильно понимаю проблему, iPhone дает вам вектор значений от акселерометров. Предполагая, что пользователь не размахивает им, этот вектор будет иметь приблизительно постоянную длину и направлен прямо вниз под действием силы тяжести.
Существует одна серьезная проблема с этим, это то, что вы не можете сказать, когда пользователь поворачивает телефон вокруг горизонтали. Представьте, что вы лежите на столе, положив телефон лицом к себе, когда сидите перед ним; вектор гравитации будет (0, -1, 0). Теперь поверните телефон на 90 градусов, чтобы дно было повернуто влево, но на столе все еще ровно. Вектор гравитации по-прежнему будет (0, -1, 0). Но вы бы действительно хотели, чтобы ваш вертолет поворачивался вместе с телефоном. Это основное ограничение того факта, что iPhone имеет только 2D-акселерометр, и он экстраполирует 3D-гравитационный вектор из этого.
Итак, давайте предположим, что вы сказали пользователю, что ему не разрешается поворачивать свой телефон таким образом, и он должен держать его с нижней точкой для вас. Это нормально, вы все равно можете получить от этого большой контроль.
Далее вам нужно ограничить входное значение таким образом, чтобы вертолет никогда не отклонялся более чем на 90 градусов по бокам. Представьте себе вектор, который вы дали как палку, прикрепленную к вашему телефону, и болтающуюся гравитацией. Вектор, который у вас есть, описывает направление силы тяжести относительно плоской поверхности телефона. Если бы это было (0, -1, 0), палка направлена прямо вниз (-y). если бы это было (1, 0, 0), ручка указывает на правую часть телефона (+ x) и подразумевает, что телефон был повернут на 90 градусов по часовой стрелке (глядя на вас на телефон).
Предположим, что в этой метафоре палка имеет полную свободу вращения. Он может указывать в любом направлении от телефона. Таким образом, перемещение палки описывает поверхность сферы. Но самое главное, вы хотите, чтобы палка могла перемещаться по нижней половине этой сферы. Если пользователь поворачивает телефон так, чтобы палка находилась в верхней половине сферы, вы хотите, чтобы он был ограничен таким образом, чтобы он указывал куда-то вокруг экватора сферы.
Вы можете достичь этого довольно чисто, используя полярные координаты. Трехмерные векторы и полярные координаты взаимозаменяемы - вы можете конвертировать в и из нее без потери какой-либо информации.
Преобразуйте ваш вектор (нормализованный, конечно) в набор трехмерных полярных координат (вы должны легко найти эту логику в сети). Это даст вам угол вокруг горизонтальной плоскости и угол для вертикальной плоскости (и расстояние от начала координат - для нормализованного вектора, это должно быть 1,0). Если вертикальный угол положительный, вектор находится в верхней половине сферы, отрицательный - в нижней половине. Затем закройте вертикальный угол так, чтобы он всегда был равен нулю или меньше (и так в нижней половине сферы). Затем вы можете взять горизонтальный и ограниченный вертикальный угол и преобразовать его обратно в вектор.
Этот новый вектор, если он подключен к уже имеющемуся матричному коду, даст вам правильную ориентацию, ограниченную диапазоном движения, который вам нужен. Также будет стабильно, если пользователь повернет свой телефон немного за отметку 90 градусов - эта логика будет держать ваш вектор направления как можно ближе к текущей ориентации пользователя, не выходя за установленные пределы.