Skip to content

Commit 17b949d

Browse files
authored
Merge pull request #29 from caternuson/webgl
Add WebGL example
2 parents d48ec14 + 9b2360a commit 17b949d

24 files changed

+115376
-0
lines changed

examples/webgl_demo/server.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Adafruit BNO055 WebGL Example
2+
#
3+
# Requires the flask web framework to be installed. See http://flask.pocoo.org/
4+
# for installation instructions, however on a Linux machine like the Raspberry
5+
# Pi or BeagleBone black you can likely install it by running:
6+
# sudo apt-get update
7+
# sudo apt-get install python3-flask
8+
#
9+
# Copyright (c) 2015 Adafruit Industries
10+
# Author: Tony DiCola
11+
# 2019 update: Carter Nelson
12+
#
13+
# Permission is hereby granted, free of charge, to any person obtaining a copy
14+
# of this software and associated documentation files (the "Software"), to deal
15+
# in the Software without restriction, including without limitation the rights
16+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17+
# copies of the Software, and to permit persons to whom the Software is
18+
# furnished to do so, subject to the following conditions:
19+
#
20+
# The above copyright notice and this permission notice shall be included in
21+
# all copies or substantial portions of the Software.
22+
#
23+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29+
# THE SOFTWARE.
30+
import json
31+
import logging
32+
import threading
33+
import time
34+
35+
from flask import *
36+
37+
import board
38+
import busio
39+
import adafruit_bno055
40+
i2c = busio.I2C(board.SCL, board.SDA)
41+
42+
# Create the BNO sensor connection.
43+
bno = adafruit_bno055.BNO055(i2c)
44+
45+
# Application configuration below. You probably don't need to change these values.
46+
47+
# How often to update the BNO sensor data (in hertz).
48+
BNO_UPDATE_FREQUENCY_HZ = 10
49+
50+
# Name of the file to store calibration data when the save/load calibration
51+
# button is pressed. Calibration data is stored in JSON format.
52+
CALIBRATION_FILE = 'calibration.json'
53+
54+
# BNO sensor axes remap values. These are the parameters to the BNO.set_axis_remap
55+
# function. Don't change these without consulting section 3.4 of the datasheet.
56+
# The default axes mapping below assumes the Adafruit BNO055 breakout is flat on
57+
# a table with the row of SDA, SCL, GND, VIN, etc pins facing away from you.
58+
#BNO_AXIS_REMAP = { 'x': BNO055.AXIS_REMAP_X,
59+
# 'y': BNO055.AXIS_REMAP_Z,
60+
# 'z': BNO055.AXIS_REMAP_Y,
61+
# 'x_sign': BNO055.AXIS_REMAP_POSITIVE,
62+
# 'y_sign': BNO055.AXIS_REMAP_POSITIVE,
63+
# 'z_sign': BNO055.AXIS_REMAP_NEGATIVE }
64+
65+
66+
# Create flask application.
67+
app = Flask(__name__)
68+
69+
# Global state to keep track of the latest readings from the BNO055 sensor.
70+
# This will be accessed from multiple threads so care needs to be taken to
71+
# protect access with a lock (or else inconsistent/partial results might be read).
72+
# A condition object is used both as a lock for safe access across threads, and
73+
# to notify threads that the BNO state has changed.
74+
bno_data = {}
75+
bno_changed = threading.Condition()
76+
77+
# Background thread to read BNO sensor data. Will be created right before
78+
# the first request is served (see start_bno_thread below).
79+
bno_thread = None
80+
81+
82+
def read_bno():
83+
"""Function to read the BNO sensor and update the bno_data object with the
84+
latest BNO orientation, etc. state. Must be run in its own thread because
85+
it will never return!
86+
"""
87+
while True:
88+
# Capture the lock on the bno_changed condition so the bno_data shared
89+
# state can be updated.
90+
with bno_changed:
91+
bno_data['euler'] = bno.euler
92+
bno_data['temp'] = bno.temperature
93+
bno_data['quaternion'] = bno.quaternion
94+
bno_data['calibration'] = bno.calibration_status
95+
# Notify any waiting threads that the BNO state has been updated.
96+
bno_changed.notifyAll()
97+
# Sleep until the next reading.
98+
time.sleep(1.0/BNO_UPDATE_FREQUENCY_HZ)
99+
100+
def bno_sse():
101+
"""Function to handle sending BNO055 sensor data to the client web browser
102+
using HTML5 server sent events (aka server push). This is a generator function
103+
that flask will run in a thread and call to get new data that is pushed to
104+
the client web page.
105+
"""
106+
# Loop forever waiting for a new BNO055 sensor reading and sending it to
107+
# the client. Since this is a generator function the yield statement is
108+
# used to return a new result.
109+
while True:
110+
# Capture the bno_changed condition lock and then wait for it to notify
111+
# a new reading is available.
112+
with bno_changed:
113+
bno_changed.wait()
114+
# A new reading is available! Grab the reading value and then give
115+
# up the lock.
116+
heading, roll, pitch = bno_data['euler']
117+
temp = bno_data['temp']
118+
x, y, z, w = bno_data['quaternion']
119+
sys, gyro, accel, mag = bno_data['calibration']
120+
# Send the data to the connected client in HTML5 server sent event format.
121+
data = {'heading': heading, 'roll': roll, 'pitch': pitch, 'temp': temp,
122+
'quatX': x, 'quatY': y, 'quatZ': z, 'quatW': w,
123+
'calSys': sys, 'calGyro': gyro, 'calAccel': accel, 'calMag': mag }
124+
yield 'data: {0}\n\n'.format(json.dumps(data))
125+
126+
127+
@app.before_first_request
128+
def start_bno_thread():
129+
# Start the BNO thread right before the first request is served. This is
130+
# necessary because in debug mode flask will start multiple main threads so
131+
# this is the only spot to put code that can only run once after starting.
132+
# See this SO question for more context:
133+
# http://stackoverflow.com/questions/24617795/starting-thread-while-running-flask-with-debug
134+
global bno_thread
135+
# Kick off BNO055 reading thread.
136+
bno_thread = threading.Thread(target=read_bno)
137+
bno_thread.daemon = True # Don't let the BNO reading thread block exiting.
138+
bno_thread.start()
139+
140+
@app.route('/bno')
141+
def bno_path():
142+
# Return SSE response and call bno_sse function to stream sensor data to
143+
# the webpage.
144+
return Response(bno_sse(), mimetype='text/event-stream')
145+
146+
@app.route('/save_calibration', methods=['POST'])
147+
def save_calibration():
148+
# Save calibration data to disk.
149+
#
150+
# TODO: implement this
151+
#
152+
return 'OK'
153+
154+
@app.route('/load_calibration', methods=['POST'])
155+
def load_calibration():
156+
# Load calibration from disk.
157+
#
158+
# TODO: implement this
159+
#
160+
return 'OK'
161+
162+
@app.route('/')
163+
def root():
164+
return render_template('index.html')
165+
166+
167+
if __name__ == '__main__':
168+
# Create a server listening for external connections on the default
169+
# port 5000. Enable debug mode for better error messages and live
170+
# reloading of the server on changes. Also make the server threaded
171+
# so multiple connections can be processed at once (very important
172+
# for using server sent events).
173+
app.run(host='0.0.0.0', debug=True, threaded=True)

examples/webgl_demo/static/bunny.mtl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# 3ds Max Wavefront OBJ Exporter v0.94b - (c)2007 guruware
2+
# File Created: 04.07.2010 10:41:39
3+
4+
newmtl Body
5+
Ns 32
6+
d 1
7+
Tr 1
8+
Tf 1 1 1
9+
illum 2
10+
Ka 0.0000 0.0000 0.0000
11+
Kd 0.7412 0.4784 0.4765
12+
Ks 0.3500 0.3500 0.6500
13+

0 commit comments

Comments
 (0)