关于 iOS 的技术解读有很多,但是却鲜有设备可视化同步的介绍文章。本文一起了解下这个酷炫的 iOS 黑科技。

我们的任务很简单——如上图所示,实时获取设备的当前方向。

UIDevice.current.orientation

首先,需要调用

beginGeneratingDeviceOrientationNotifications()

但仅仅这样还不行。因为如果设备上的旋转被锁定了,那么就不会产生以上通知。我的相机应用程序从头到尾都需要知道方向——所以我意识到我需要直接根据设备的加速度计算方向。

好了,现在有了这些值,我们该做些什么呢?这是一个较难的部分。如果将所有内容都输出到控制台,那么我们很快就会被大量数据淹没。我认为还是在屏幕上显示这些值比较好。

但是,等等,如果将数值显示在图表上,会怎么样?别想图表了,我们可以来用开源的 Blender 试试,它可以实现这些值的可视化,并且很容易扩展。

然而 Blender 并不是很好的代码编辑器,所以我们还是使用钟爱的外部编辑器吧。为了调用外部文件,我们可以将 print("hi") 替换成以下代码:

import bpy

import os

filename = os.path.join(os.path.dirname(bpy.data.filepath), "server.py")

exec(compile(open(filename).read(), filename, ‘exec‘))

下一步,我们需要在与 .blend 文件相同的文件夹中创建新的 server.py 文件,我们真正的代码就要保存在这里。现在我们可以用任何编辑器打开它,你可以选择 Atom、Sublime,甚至 Word 2007 都行。

找到该 Cube 对象,点击右键并选择重命名,重命名为 iPhone。现在让我们再来看一看 server.py。

import socket

import select

import json

import threading

import traceback

class ServerThread(threading.Thread):

def __init__(self):

threading.Thread.__init__(self)

self.running = True

def stopServer(self):

self.running = False

self.server.running = False

def run(self):

try:

self.server = Server()

while self.running:

self.server.receive()

except:

pass

class Server:

def __init__(self):

self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

self.socket.setblocking(False)

self.socket.bind((str(socket.INADDR_ANY), 9845))

self.socket.listen(2)

self.running = True

def __exit__(self, exc_type, exc_value, traceback):

self.socket.close()

def receive(self):

pairs = []

timeout = 1

while self.running:

sockets = list(map(lambda x: x[0], pairs))

if len(pairs) > 0:

read_sockets, write_sockets, error_sockets = select.select(sockets, [], [], timeout)

for sock in read_sockets:

data = sock.recv(4096)

if not data :

print(‘Client disconnected‘)

pairs = []

else :

self.connectionReceivedData(connection, data.decode())

try:

try:

connection,address = self.socket.accept()

print("new connection: ", connection)

pairs.append((connection, address))

except:

pass

except:

pass

for pair in pairs:

(connection, address) = pair

connection.close()

def connectionReceivedData(self, connection, data):

try:

motionData = json.loads(data)

except json.decoder.JSONDecodeError:

print("Invalid JSON: ", data)

return None

receivedMotionData(motionData)

# This is a global so when we run the script again, we can keep the server alive

# but change how it works

import bpy

def receivedMotionData(motionData):

phone = bpy.context.scene.objects["iPhone"]

phone.rotation_quaternion.x = float(motionData[‘x‘])

phone.rotation_quaternion.y = 0 - float(motionData[‘z‘])

phone.rotation_quaternion.z = float(motionData[‘y‘])

phone.rotation_quaternion.w = float(motionData[‘w‘])

pass

try:

if serverThread.running == False:

serverThread = ServerThread()

serverThread.start()

print("Starting server")

else:

print("Server already running, using new motion handler.")

except:

serverThread = ServerThread()

serverThread.start()

print("Starting server")

检查 Blender,你应该看到 iPhone 根本没有改变。这是因为上面的脚本使用四元组设置了 iPhone 的旋转角度,并且它使用了欧拉角进行旋转。需要做一些修改。将 Python 控制台面切换到 “Properties”,然后单击该面板顶部的橙色立方体图标。中部 Transform 的下面,点击 XYZ Euler 并选择 Quaternion。现在尝试再次运行 client.py。

你应该看到 iPhone 立即翻转过来了。不要惊慌,这就是我们想要的。现在,我们需要让这个模型跟着实际的 iPhone 旋转。

我们需要将运动数据从 iPhone 发送到运行 Blender 的计算机。感谢上苍我们不需要深入到 Swift 中的原始 C 套接字级别,因为 Foundation 具有抽象。

我们可以将以下代码放入新的 iOS 项目中,以替换默认的 ViewController。请确保使用计算机的本地 IP 地址替换 host 变量。

import UIKit

import CoreMotion

class CoreMotionViewController: UIViewController, StreamDelegate {

let motionManager = CMMotionManager()

let queue = OperationQueue()

let host = "192.168.1.2"

override func viewDidLoad() {

super.viewDidLoad()

setUpStreams(host: host)

motionManager.startDeviceMotionUpdates(to: queue) { (data: CMDeviceMotion?, error: Error?) in

guard let data = data else {

print("Error: \(error!)")

return

}

let attitude: CMAttitude = data.attitude

let quaternion = attitude.quaternion

var motionData = MotionData()

motionData.x = quaternion.x

motionData.y = quaternion.y

motionData.z = quaternion.z

motionData.w = quaternion.w

let encoder = JSONEncoder()

do {

let json = try encoder.encode(motionData)

self.send(data: json)

} catch let error {

print("Couldn‘t send data, error: \(error)")

}

}

}

// MARK: - Streams

var inputStream: InputStream?

var outputStream: OutputStream?

func setUpStreams(host: String) {

var readStream: Unmanaged?

var writeStream: Unmanaged?

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,

host as CFString, 9845,

&readStream,

&writeStream)

inputStream = readStream!.takeRetainedValue()

outputStream = writeStream!.takeRetainedValue()

guard let inputStream = inputStream, let outputStream = outputStream else {

print("Failed to create streams")

return

}

inputStream.delegate = self

outputStream.delegate = self

inputStream.schedule(in: .current, forMode: .commonModes)

outputStream.schedule(in: .current, forMode: .commonModes)

inputStream.open()

outputStream.open()

}

func send(data: Data) {

guard let outputStream = outputStream else {

return

}

_ = data.withUnsafeBytes {

outputStream.write($0, maxLength: data.count)

}

}

func stream(_ aStream: Stream, handle eventCode: Stream.Event) {

if eventCode == .errorOccurred {

inputStream = nil

outputStream = nil

print("Error: Stream error")

} else if eventCode == .endEncountered {

inputStream = nil

outputStream = nil

print("Error: Encountered end of stream")

}

let maxReadLength = 4096

if eventCode == .hasBytesAvailable {

guard let inputStream = inputStream else {

return

}

while inputStream.hasBytesAvailable {

let buffer = UnsafeMutablePointer.allocate(capacity: maxReadLength)

inputStream.read(buffer, maxLength: maxReadLength)

buffer.deallocate()

}

}

}

}

// MARK: - Data Model

private struct MotionData: Codable {

var x: Double = 0

var y: Double = 0

var z: Double = 0

var w: Double = 0

}

那么最终我是如何从移动管理器获取方向信息的?

欢迎关注我的博客或者公众号:https://home.cnblogs.com/u/Python1234/ Python学习交流

苹果手机运行python_iPhone是卖的最好的手机?用Python照样把他玩弄鼓掌之间!相关推荐

  1. 手机python软件哪个好_iPhone是卖的最好的手机?用Python照样把他玩弄鼓掌之间!...

    关于 iOS 的技术解读有很多,但是却鲜有设备可视化同步的介绍文章.本文一起了解下这个酷炫的 iOS 黑科技. 我们的任务很简单--如上图所示,实时获取设备的当前方向. UIDevice.curren ...

  2. 苹果手机运行服务器无响应是怎么回事,苹果手机运行卡顿?做好这几步操作,轻松告别手机卡顿!...

    原标题:苹果手机运行卡顿?做好这几步操作,轻松告别手机卡顿! iPhone入手一段时间后,不少朋友都出现了iPhone卡顿的现象.那么如何解决iPhone卡顿,进一步优化提升iPhone的运行速度呢? ...

  3. 苹果6设置流量显示无服务器,超实用!15个苹果手机的隐藏功能,不看你手机就白买了!...

    原标题:超实用!15个苹果手机的隐藏功能,不看你手机就白买了! 平时出门什么都可以不带,除了手机 (小编的手机简直是长在了手上) 在用苹果手机的宝宝们 知不知道你的苹果手机 还有这些隐藏的功能? 快速 ...

  4. 英特尔卖了通信与手机处理器,中国厂商是哭还是笑?

    英特尔卖了通信与手机处理器,中国厂商是哭还是笑? 上网时间:2006年06月29日   打印版 推荐给同仁发送查询 作者:孙昌旭 想不到今年初英特尔与摩托罗拉手机.中国移动的一场"Intel ...

  5. 苹果手机怎么连接蓝牙耳机_苹果手机用什么蓝牙耳机好,适配iphone手机的蓝牙耳机...

    原标题:苹果手机用什么蓝牙耳机好,适配iphone手机的蓝牙耳机 作为一名蓝牙耳机行业的从业人员,从16年入行开始就一直有朋友会咨询我关于蓝牙耳机哪个品牌最好的问题,现在蓝牙耳机品牌确实太多,对于苹果 ...

  6. sae-v2ex 一个运行在SAE上的类似v2ex的轻型python论坛 - 技术讨论 - 云计算开发者社区 - Powered by Discuz!...

    sae-v2ex 一个运行在SAE上的类似v2ex的轻型python论坛 - 技术讨论 - 云计算开发者社区 - Powered by Discuz! sae-v2ex 一个运行在SAE上的类似v2e ...

  7. 苹果手机计算机隐藏应用,超实用!15个苹果手机的隐藏功能,不看你手机就白买了!...

    原标题:超实用!15个苹果手机的隐藏功能,不看你手机就白买了! 平时出门什么都可以不带,除了手机 (小编的手机简直是长在了手上) 在用苹果手机的宝宝们 知不知道你的苹果手机 还有这些隐藏的功能? 快速 ...

  8. python开发环境和运行环境的区别_Python 初学者必知:Python 运行与开发环境

    http://codingdao.com/wp/post/py-must-know-run-dev-env/ Python 初学者必知:Python 运行与开发环境 2011年2月11日 Breake ...

  9. python获取子进程返回值_Python 从subprocess运行的子进程中实时获取输出的例子 Python如何抓取程序的输出?...

    关于python中用subprocess调用exe子进程的问题不懂我的人有什么资格对我指指点点,不了解我的人凭什么对我说三道四的. python杀死子进程后继续执行后面程序 程序a(python写成) ...

最新文章

  1. Table——高淇JAVA300讲笔记之Guava
  2. 微信小程序 PDF下载打印
  3. python删除文件和linux删除文件区别_使用Python批量删除文件列表
  4. java 字符查找 截断_java字符串常用操作(查找、截取、分割)
  5. varnish几个工具命令行工作情况
  6. Linux驱动概念扫盲篇
  7. 计算机辅助翻译入门试题,2011级计算机辅助翻译考试试题纸(A卷)
  8. 魔法值(【CCF】NOI Online能力测试3 提高组)
  9. PHP里面最难的是那部分,那个PHP中号称最难的‘递归函数’
  10. 常用的数据库索引优化语句总结
  11. 计算机桌面鼠标锁定了怎么办,笔记本鼠标锁住怎么办
  12. Windows远程桌面实现之二(抓屏技术之MirrorDriver镜像驱动开发)
  13. 两平面间8参数变换参数求解简单原理解析(已更新间接平差算法)
  14. 有效管理“刺头”员工的方法
  15. 三极管场效应参数全集
  16. cpuid limit_Max CPUID Valut Limit 请懂电脑的解答下 谢谢!
  17. 【牛腩】-母版图片不显示问题
  18. Python知识点总结——fractions(分数模块)
  19. VB6不能加载MSCOMCTL.OCX
  20. java.lang.NoClassDefFoundError: com/sun/star/lang/DisposedException

热门文章

  1. .NET Core微服务之基于IdentityServer建立授权与验证服务
  2. IdentityServer4(10)- 添加对外部认证的支持之QQ登录
  3. visual studio for mac的离线安装初体验
  4. ASP.NET Core MVC 与 Visual Studio 入门
  5. C# XML添加删除/SelectNodes/xpath
  6. C# JObject转换JSON文件相关处理
  7. C#弹窗提示并自动关闭方法
  8. Android之自定义View实现带4圆角或者2圆角的效果
  9. C++之STL之priority_queue
  10. linux之如何复制文件夹所有文件到其它文件夹