美文网首页码农的世界python热爱者
iPhone是卖的最好的手机?用Python照样把他玩弄鼓掌之间

iPhone是卖的最好的手机?用Python照样把他玩弄鼓掌之间

作者: Python树苗 | 来源:发表于2018-06-05 16:49 被阅读4次

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

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

UIDevice.current.orientation

首先,需要调用

beginGeneratingDeviceOrientationNotifications()

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

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

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

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

import bpyimport osfilename = 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。

importsocketimportselectimportjsonimportthreadingimporttracebackclassServerThread(threading.Thread):def__init__(self):threading.Thread.__init__(self) self.running =TruedefstopServer(self):self.running =Falseself.server.running =Falsedefrun(self):try: self.server = Server()whileself.running: self.server.receive()except:passclassServer: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 =Truedef__exit__(self, exc_type, exc_value, traceback):self.socket.close()defreceive(self):pairs = [] timeout =1whileself.running: sockets = list(map(lambdax: x[0], pairs))iflen(pairs) >0: read_sockets, write_sockets, error_sockets = select.select(sockets, [], [], timeout)forsockinread_sockets: data = sock.recv(4096)ifnotdata : 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:passexcept:passforpairinpairs: (connection, address) = pair connection.close()defconnectionReceivedData(self, connection, data):try: motionData = json.loads(data)exceptjson.decoder.JSONDecodeError: print("Invalid JSON: ", data)returnNonereceivedMotionData(motionData)# This is a global so when we run the script again, we can keep the server alive# but change how it worksimportbpydefreceivedMotionData(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'])passtry:ifserverThread.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 变量。

importUIKitimportCoreMotionclassCoreMotionViewController:UIViewController,StreamDelegate{letmotionManager =CMMotionManager()letqueue =OperationQueue()lethost ="192.168.1.2"overridefuncviewDidLoad(){super.viewDidLoad() setUpStreams(host: host) motionManager.startDeviceMotionUpdates(to: queue) { (data:CMDeviceMotion?, error:Error?)inguardletdata = dataelse{print("Error:\(error!)")return}letattitude:CMAttitude= data.attitudeletquaternion = attitude.quaternionvarmotionData =MotionData() motionData.x = quaternion.x motionData.y = quaternion.y motionData.z = quaternion.z motionData.w = quaternion.wletencoder =JSONEncoder()do{letjson =tryencoder.encode(motionData)self.send(data: json) }catchleterror {print("Couldn't send data, error:\(error)") } } }// MARK: - StreamsvarinputStream:InputStream?varoutputStream:OutputStream?funcsetUpStreams(host: String){varreadStream:Unmanaged?varwriteStream:Unmanaged?CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostasCFString,9845, &readStream, &writeStream) inputStream = readStream!.takeRetainedValue() outputStream = writeStream!.takeRetainedValue()guardletinputStream = inputStream,letoutputStream = outputStreamelse{print("Failed to create streams")return} inputStream.delegate =selfoutputStream.delegate =selfinputStream.schedule(in: .current, forMode: .commonModes) outputStream.schedule(in: .current, forMode: .commonModes) inputStream.open() outputStream.open() }funcsend(data: Data){guardletoutputStream = outputStreamelse{return}_= data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) } }funcstream(_aStream: Stream, handle eventCode: Stream.Event){ifeventCode == .errorOccurred { inputStream =niloutputStream =nilprint("Error: Stream error") }elseifeventCode == .endEncountered { inputStream =niloutputStream =nilprint("Error: Encountered end of stream") }letmaxReadLength =4096ifeventCode == .hasBytesAvailable {guardletinputStream = inputStreamelse{return}whileinputStream.hasBytesAvailable {letbuffer =UnsafeMutablePointer.allocate(capacity: maxReadLength) inputStream.read(buffer, maxLength: maxReadLength) buffer.deallocate() } } }}// MARK: - Data ModelprivatestructMotionData:Codable{varx:Double=0vary:Double=0varz:Double=0varw:Double=0}

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

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

欢迎加入我的千人交流学习答疑群:125240963

相关文章

  • iPhone是卖的最好的手机?用Python照样把他玩弄鼓掌之间

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

  • 天殇

    天殇,天殇,天玩弄我等世俗于鼓掌之间,又岂会伤。

  • 怪盗基德--偷心魔术师

    以星辰般不可数的面容与声音,玩弄警察于鼓掌之间的天才型罪犯。--题记 我第一次见到他,是在手机浏览器的头条新闻中。...

  • 2019-01-26

    生命是一种回声,你把最好的给予了别人,就会从别人那里获得最好的回报。人与人之间,相互鼓励是最难得的真诚。为别人鼓掌...

  • 苹果手机的商业模式

    当诺基亚还在卖手机的时候,当摩托罗拉还在卖手机的时候,苹果电脑的iPhone已经开始卖后面的商业平台,他不在只是卖...

  • 都9102年了,iPhone8/8p还值得购买吗?

    我是一家数码网店的老板,现在店里除了iPhone Xs和XR,卖的最好的就是iPhone8和iPhone8p了,一...

  • 战国人物之颜率

    战国时期,东周朝廷有这样一个人,他把秦国与齐国玩弄于鼓掌,还能安然无恙。 事情经过是这样的。 01 诱搬救兵 秦国...

  • 奈落是如何把他的分身玩弄于股掌之间的?

    奈落公认的很聪明,也很自负,所有计谋都靠自己想出来,没有找过军师。所以他的帮手也由他自己创造——也就是无数个分身。...

  • 付爱宝特种兵本周总结

    人与人之间,相互的鼓励是最难得的真诚!为别人鼓掌的人,也是给自己的生命加油!生命是一种回声,你把最好的给予...

  • 转之(股海游龙老师)

    人与人之间, 相互的鼓励是最难得的真诚! 为别人鼓掌的人, 也是给自己的生命加油! 生命是一种回声, 你把最好的给...

网友评论

    本文标题:iPhone是卖的最好的手机?用Python照样把他玩弄鼓掌之间

    本文链接:https://www.haomeiwen.com/subject/tohmsftx.html