From 623351e4edb01b7c66612e43e5e8ebefd237276d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Sat, 5 Aug 2023 07:15:35 -0700 Subject: [PATCH] Revert "[commabody] Add new body teleop ui (#29119)" (#29249) This reverts commit a7304d059cb2f4e57e64fcbabb4f9079f1ea659d. --- .pre-commit-config.yaml | 2 +- selfdrive/manager/process_config.py | 2 +- tools/bodyteleop/.gitignore | 4 - tools/bodyteleop/bodyav.py | 158 ------------------ tools/bodyteleop/static/index.html | 103 ------------ tools/bodyteleop/static/js/controls.js | 54 ------ tools/bodyteleop/static/js/jsmain.js | 23 --- tools/bodyteleop/static/js/plots.js | 53 ------ tools/bodyteleop/static/js/webrtc.js | 217 ------------------------- tools/bodyteleop/static/main.css | 185 --------------------- tools/bodyteleop/static/poster.png | Bin 8297 -> 0 bytes tools/bodyteleop/web.py | 201 ----------------------- tools/joystick/web.py | 78 +++++++++ 13 files changed, 80 insertions(+), 1000 deletions(-) delete mode 100644 tools/bodyteleop/.gitignore delete mode 100644 tools/bodyteleop/bodyav.py delete mode 100644 tools/bodyteleop/static/index.html delete mode 100644 tools/bodyteleop/static/js/controls.js delete mode 100644 tools/bodyteleop/static/js/jsmain.js delete mode 100644 tools/bodyteleop/static/js/plots.js delete mode 100644 tools/bodyteleop/static/js/webrtc.js delete mode 100644 tools/bodyteleop/static/main.css delete mode 100644 tools/bodyteleop/static/poster.png delete mode 100644 tools/bodyteleop/web.py create mode 100755 tools/joystick/web.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 95d78ffde8..c13d2475ff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: exclude: '^(third_party/)|(body/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)' args: # if you've got a short variable name that's getting flagged, add it here - - -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie + - -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup - --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US - repo: local hooks: diff --git a/selfdrive/manager/process_config.py b/selfdrive/manager/process_config.py index 2fd786875c..f151a51d10 100644 --- a/selfdrive/manager/process_config.py +++ b/selfdrive/manager/process_config.py @@ -72,7 +72,7 @@ procs = [ # debug procs NativeProcess("bridge", "cereal/messaging", ["./bridge"], onroad=False, callback=notcar), - PythonProcess("webjoystick", "tools.bodyteleop.web", onroad=False, callback=notcar), + PythonProcess("webjoystick", "tools.joystick.web", onroad=False, callback=notcar), ] managed_processes = {p.name: p for p in procs} diff --git a/tools/bodyteleop/.gitignore b/tools/bodyteleop/.gitignore deleted file mode 100644 index adeab99a95..0000000000 --- a/tools/bodyteleop/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -av -av-10.0.0/* -key.pem -cert.pem \ No newline at end of file diff --git a/tools/bodyteleop/bodyav.py b/tools/bodyteleop/bodyav.py deleted file mode 100644 index cb2ebb061a..0000000000 --- a/tools/bodyteleop/bodyav.py +++ /dev/null @@ -1,158 +0,0 @@ -import asyncio -import io -import numpy as np -import pyaudio -import wave - -from aiortc.contrib.media import MediaBlackhole -from aiortc.mediastreams import AudioStreamTrack, MediaStreamError, MediaStreamTrack -from aiortc.mediastreams import VIDEO_CLOCK_RATE, VIDEO_TIME_BASE -from aiortc.rtcrtpsender import RTCRtpSender -from av import CodecContext, Packet -from pydub import AudioSegment -import cereal.messaging as messaging - -AUDIO_RATE = 16000 -SOUNDS = { - 'engage': '../../selfdrive/assets/sounds/engage.wav', - 'disengage': '../../selfdrive/assets/sounds/disengage.wav', - 'error': '../../selfdrive/assets/sounds/warning_immediate.wav', -} - - -def force_codec(pc, sender, forced_codec='video/VP9', stream_type="video"): - codecs = RTCRtpSender.getCapabilities(stream_type).codecs - codec = [codec for codec in codecs if codec.mimeType == forced_codec] - transceiver = next(t for t in pc.getTransceivers() if t.sender == sender) - transceiver.setCodecPreferences(codec) - - -class EncodedBodyVideo(MediaStreamTrack): - kind = "video" - - _start: float - _timestamp: int - - def __init__(self): - super().__init__() - sock_name = 'livestreamDriverEncodeData' - messaging.context = messaging.Context() - self.sock = messaging.sub_sock(sock_name, None, conflate=True) - self.pts = 0 - - async def recv(self) -> Packet: - while True: - msg = messaging.recv_one_or_none(self.sock) - if msg is not None: - break - await asyncio.sleep(0.005) - - evta = getattr(msg, msg.which()) - self.last_idx = evta.idx.encodeId - - packet = Packet(evta.header + evta.data) - packet.time_base = VIDEO_TIME_BASE - packet.pts = self.pts - self.pts += 0.05 * VIDEO_CLOCK_RATE - return packet - - -class WebClientSpeaker(MediaBlackhole): - def __init__(self): - super().__init__() - self.p = pyaudio.PyAudio() - self.buffer = io.BytesIO() - self.channels = 2 - self.stream = self.p.open(format=pyaudio.paInt16, channels=self.channels, rate=48000, frames_per_buffer=9600, output=True, stream_callback=self.pyaudio_callback) - - def pyaudio_callback(self, in_data, frame_count, time_info, status): - if self.buffer.getbuffer().nbytes < frame_count * self.channels * 2: - buff = np.zeros((frame_count, 2), dtype=np.int16).tobytes() - elif self.buffer.getbuffer().nbytes > 115200: # 3x the usual read size - self.buffer.seek(0) - buff = self.buffer.read(frame_count * self.channels * 4) - buff = buff[:frame_count * self.channels * 2] - self.buffer.seek(2) - else: - self.buffer.seek(0) - buff = self.buffer.read(frame_count * self.channels * 2) - self.buffer.seek(2) - return (buff, pyaudio.paContinue) - - async def consume(self, track): - while True: - try: - frame = await track.recv() - except MediaStreamError: - return - bio = bytes(frame.planes[0]) - self.buffer.write(bio) - - async def start(self): - for track, task in self._MediaBlackhole__tracks.items(): # pylint: disable=access-member-before-definition - if task is None: - self._MediaBlackhole__tracks[track] = asyncio.ensure_future(self.consume(track)) - - async def stop(self): - for task in self._MediaBlackhole__tracks.values(): # pylint: disable=access-member-before-definition - if task is not None: - task.cancel() - self._MediaBlackhole__tracks = {} - self.stream.stop_stream() - self.stream.close() - self.p.terminate() - - -class BodyMic(AudioStreamTrack): - def __init__(self): - super().__init__() - - self.sample_rate = AUDIO_RATE - self.AUDIO_PTIME = 0.020 # 20ms audio packetization - self.samples = int(self.AUDIO_PTIME * self.sample_rate) - self.FORMAT = pyaudio.paInt16 - self.CHANNELS = 2 - self.RATE = self.sample_rate - self.CHUNK = int(AUDIO_RATE * 0.020) - self.p = pyaudio.PyAudio() - self.mic_stream = self.p.open(format=self.FORMAT, channels=1, rate=self.RATE, input=True, frames_per_buffer=self.CHUNK) - - self.codec = CodecContext.create('pcm_s16le', 'r') - self.codec.sample_rate = self.RATE - self.codec.channels = 2 - self.audio_samples = 0 - self.chunk_number = 0 - - async def recv(self): - mic_data = self.mic_stream.read(self.CHUNK) - mic_sound = AudioSegment(mic_data, sample_width=2, channels=1, frame_rate=self.RATE) - mic_sound = AudioSegment.from_mono_audiosegments(mic_sound, mic_sound) - mic_sound += 3 # increase volume by 3db - packet = Packet(mic_sound.raw_data) - frame = self.codec.decode(packet)[0] - frame.pts = self.audio_samples - self.audio_samples += frame.samples - self.chunk_number = self.chunk_number + 1 - return frame - - -async def play_sound(sound): - chunk = 5120 - with wave.open(SOUNDS[sound], 'rb') as wf: - def callback(in_data, frame_count, time_info, status): - data = wf.readframes(frame_count) - return data, pyaudio.paContinue - - p = pyaudio.PyAudio() - stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), - channels=wf.getnchannels(), - rate=wf.getframerate(), - output=True, - frames_per_buffer=chunk, - stream_callback=callback) - stream.start_stream() - while stream.is_active(): - await asyncio.sleep(0) - stream.stop_stream() - stream.close() - p.terminate() diff --git a/tools/bodyteleop/static/index.html b/tools/bodyteleop/static/index.html deleted file mode 100644 index 3654769756..0000000000 --- a/tools/bodyteleop/static/index.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - commabody - - - - - - - - - - -
-

comma body

- - -
-
-
-
-
- - - -
-

body

-
-
-
- - -
-

you

-
-
-
-
-
-
-
- - -
-

ping time

-
-
-
- - -
-

battery

-
-
-
- -
-
-
-
-
-
W
-
0,0x,y
-
-
-
A
-
S
-
D
-
-
-
- - - - -
-
-
-
-
-
-

Play Sounds

-
-
- - - -
-
-
-
-
-
-
-
-
-
- - - diff --git a/tools/bodyteleop/static/js/controls.js b/tools/bodyteleop/static/js/controls.js deleted file mode 100644 index b1e0e7ee70..0000000000 --- a/tools/bodyteleop/static/js/controls.js +++ /dev/null @@ -1,54 +0,0 @@ -const keyVals = {w: 0, a: 0, s: 0, d: 0} - -export function getXY() { - let x = -keyVals.w + keyVals.s - let y = -keyVals.d + keyVals.a - return {x, y} -} - -export const handleKeyX = (key, setValue) => { - if (['w', 'a', 's', 'd'].includes(key)){ - keyVals[key] = setValue; - let color = "#333"; - if (setValue === 1){ - color = "#e74c3c"; - } - $("#key-"+key).css('background', color); - const {x, y} = getXY(); - $("#pos-vals").text(x+","+y); - } -}; - -export async function executePlan() { - let plan = $("#plan-text").val(); - const planList = []; - plan.split("\n").forEach(function(e){ - let line = e.split(",").map(k=>parseInt(k)); - if (line.length != 5 || line.slice(0, 4).map(e=>[1, 0].includes(e)).includes(false) || line[4] < 0 || line[4] > 10){ - console.log("invalid plan"); - } - else{ - planList.push(line) - } - }); - - async function execute() { - for (var i = 0; i < planList.length; i++) { - let [w, a, s, d, t] = planList[i]; - while(t > 0){ - console.log(w, a, s, d, t); - if(w==1){$("#key-w").mousedown();} - if(a==1){$("#key-a").mousedown();} - if(s==1){$("#key-s").mousedown();} - if(d==1){$("#key-d").mousedown();} - await sleep(50); - $("#key-w").mouseup(); - $("#key-a").mouseup(); - $("#key-s").mouseup(); - $("#key-d").mouseup(); - t = t - 0.05; - } - } - } - execute(); -} \ No newline at end of file diff --git a/tools/bodyteleop/static/js/jsmain.js b/tools/bodyteleop/static/js/jsmain.js deleted file mode 100644 index f521905724..0000000000 --- a/tools/bodyteleop/static/js/jsmain.js +++ /dev/null @@ -1,23 +0,0 @@ -import { handleKeyX, executePlan } from "./controls.js"; -import { start, stop, last_ping } from "./webrtc.js"; - -export var pc = null; -export var dc = null; - -document.addEventListener('keydown', (e)=>(handleKeyX(e.key.toLowerCase(), 1))); -document.addEventListener('keyup', (e)=>(handleKeyX(e.key.toLowerCase(), 0))); -$(".keys").bind("mousedown touchstart", (e)=>handleKeyX($(e.target).attr('id').replace('key-', ''), 1)); -$(".keys").bind("mouseup touchend", (e)=>handleKeyX($(e.target).attr('id').replace('key-', ''), 0)); -$("#plan-button").click(executePlan); - -setInterval( () => { - const dt = new Date().getTime(); - if ((dt - last_ping) > 1000) { - $(".pre-blob").removeClass('blob'); - $("#battery").text("-"); - $("#ping-time").text('-'); - $("video")[0].load(); - } -}, 5000); - -start(pc, dc); \ No newline at end of file diff --git a/tools/bodyteleop/static/js/plots.js b/tools/bodyteleop/static/js/plots.js deleted file mode 100644 index 5327bf71be..0000000000 --- a/tools/bodyteleop/static/js/plots.js +++ /dev/null @@ -1,53 +0,0 @@ -export const pingPoints = []; -export const batteryPoints = []; - -function getChartConfig(pts, color, title, ymax=100) { - return { - type: 'line', - data: { - datasets: [{ - label: title, - data: pts, - borderWidth: 1, - borderColor: color, - backgroundColor: color, - fill: 'origin' - }] - }, - options: { - scales: { - x: { - type: 'time', - time: { - unit: 'minute', - displayFormats: { - second: 'h:mm a' - } - }, - grid: { - color: '#222', // Grid lines color - }, - ticks: { - source: 'data', - fontColor: 'rgba(255, 255, 255, 1.0)', // Y-axis label color - } - }, - y: { - beginAtZero: true, - max: ymax, - grid: { - color: 'rgba(255, 255, 255, 0.1)', // Grid lines color - }, - ticks: { - fontColor: 'rgba(255, 255, 255, 0.7)', // Y-axis label color - } - } - } - } - } -} - -const ctxPing = document.getElementById('chart-ping'); -const ctxBattery = document.getElementById('chart-battery'); -export const chartPing = new Chart(ctxPing, getChartConfig(pingPoints, 'rgba(192, 57, 43, 0.7)', 'Controls Ping Time (ms)', 250)); -export const chartBattery = new Chart(ctxBattery, getChartConfig(batteryPoints, 'rgba(41, 128, 185, 0.7)', 'Battery %', 100)); diff --git a/tools/bodyteleop/static/js/webrtc.js b/tools/bodyteleop/static/js/webrtc.js deleted file mode 100644 index 8bc8e77317..0000000000 --- a/tools/bodyteleop/static/js/webrtc.js +++ /dev/null @@ -1,217 +0,0 @@ -import { getXY } from "./controls.js"; -import { pingPoints, batteryPoints, chartPing, chartBattery } from "./plots.js"; - -export let dcInterval = null; -export let batteryInterval = null; -export let last_ping = null; - - -export function createPeerConnection(pc) { - var config = { - sdpSemantics: 'unified-plan' - }; - - pc = new RTCPeerConnection(config); - - // connect audio / video - pc.addEventListener('track', function(evt) { - console.log("Adding Tracks!") - if (evt.track.kind == 'video') - document.getElementById('video').srcObject = evt.streams[0]; - else - document.getElementById('audio').srcObject = evt.streams[0]; - }); - return pc; -} - - -export function negotiate(pc) { - return pc.createOffer({offerToReceiveAudio:true, offerToReceiveVideo:true}).then(function(offer) { - return pc.setLocalDescription(offer); - }).then(function() { - return new Promise(function(resolve) { - if (pc.iceGatheringState === 'complete') { - resolve(); - } - else { - function checkState() { - if (pc.iceGatheringState === 'complete') { - pc.removeEventListener('icegatheringstatechange', checkState); - resolve(); - } - } - pc.addEventListener('icegatheringstatechange', checkState); - } - }); - }).then(function() { - var offer = pc.localDescription; - return fetch('/offer', { - body: JSON.stringify({ - sdp: offer.sdp, - type: offer.type, - }), - headers: { - 'Content-Type': 'application/json' - }, - method: 'POST' - }); - }).then(function(response) { - console.log(response); - return response.json(); - }).then(function(answer) { - return pc.setRemoteDescription(answer); - }).catch(function(e) { - alert(e); - }); -} - - -function isMobile() { - let check = false; - (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); - return check; -}; - - -export const constraints = { - audio: { - autoGainControl: false, - sampleRate: 48000, - sampleSize: 16, - echoCancellation: true, - noiseSuppression: true, - channelCount: 1 - }, - video: isMobile() -}; - - -export function createDummyVideoTrack() { - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - - const frameWidth = 5; // Set the width of the frame - const frameHeight = 5; // Set the height of the frame - canvas.width = frameWidth; - canvas.height = frameHeight; - - context.fillStyle = 'black'; - context.fillRect(0, 0, frameWidth, frameHeight); - - const stream = canvas.captureStream(); - const videoTrack = stream.getVideoTracks()[0]; - - return videoTrack; -} - - -export function start(pc, dc) { - pc = createPeerConnection(pc); - - if (constraints.audio || constraints.video) { - // add audio track - navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { - stream.getTracks().forEach(function(track) { - pc.addTrack(track, stream); - // only audio? - // if (track.kind === 'audio'){ - // pc.addTrack(track, stream); - // } - }); - return negotiate(pc); - }, function(err) { - alert('Could not acquire media: ' + err); - }); - - // add a fake video? - // const dummyVideoTrack = createDummyVideoTrack(); - // const dummyMediaStream = new MediaStream(); - // dummyMediaStream.addTrack(dummyVideoTrack); - // pc.addTrack(dummyVideoTrack, dummyMediaStream); - - } else { - negotiate(pc); - } - - // setInterval(() => {pc.getStats(null).then((stats) => {stats.forEach((report) => console.log(report))})}, 10000) - // var video = document.querySelector('video'); - // var print = function (e, f){console.log(e, f); video.requestVideoFrameCallback(print);}; - // video.requestVideoFrameCallback(print); - - - var parameters = {"ordered": true}; - dc = pc.createDataChannel('data', parameters); - dc.onclose = function() { - console.log("data channel closed"); - clearInterval(dcInterval); - clearInterval(batteryInterval); - }; - function controlCommand() { - const {x, y} = getXY(); - const dt = new Date().getTime(); - var message = JSON.stringify({type: 'control_command', x, y, dt}); - dc.send(message); - } - - function batteryLevel() { - var message = JSON.stringify({type: 'battery_level'}); - dc.send(message); - } - - dc.onopen = function() { - dcInterval = setInterval(controlCommand, 50); - batteryInterval = setInterval(batteryLevel, 10000); - controlCommand(); - batteryLevel(); - $(".sound").click((e)=>{ - const sound = $(e.target).attr('id').replace('sound-', '') - dc.send(JSON.stringify({type: 'play_sound', sound})); - }); - }; - - let val_print_idx = 0; - dc.onmessage = function(evt) { - const data = JSON.parse(evt.data); - if(val_print_idx == 0 && data.type === 'ping_time') { - const dt = new Date().getTime(); - const pingtime = dt - data.incoming_time; - pingPoints.push({'x': dt, 'y': pingtime}); - if (pingPoints.length > 1000) { - pingPoints.shift(); - } - chartPing.update(); - $("#ping-time").text((pingtime) + "ms"); - last_ping = dt; - $(".pre-blob").addClass('blob'); - } - val_print_idx = (val_print_idx + 1 ) % 20; - if(data.type === 'battery_level') { - $("#battery").text(data.value + "%"); - batteryPoints.push({'x': new Date().getTime(), 'y': data.value}); - if (batteryPoints.length > 1000) { - batteryPoints.shift(); - } - chartBattery.update(); - } - }; -} - - -export function stop(pc, dc) { - if (dc) { - dc.close(); - } - if (pc.getTransceivers) { - pc.getTransceivers().forEach(function(transceiver) { - if (transceiver.stop) { - transceiver.stop(); - } - }); - } - pc.getSenders().forEach(function(sender) { - sender.track.stop(); - }); - setTimeout(function() { - pc.close(); - }, 500); -} diff --git a/tools/bodyteleop/static/main.css b/tools/bodyteleop/static/main.css deleted file mode 100644 index 1bfb5982b4..0000000000 --- a/tools/bodyteleop/static/main.css +++ /dev/null @@ -1,185 +0,0 @@ -body { - background: #333 !important; - color: #fff !important; - display: flex; - justify-content: center; - align-items: start; -} - -p { - margin: 0px !important; -} - -i { - font-style: normal; -} - -.small { - font-size: 1em !important -} - -.jumbo { - font-size: 8rem; -} - - -@media (max-width: 600px) { - .small { - font-size: 0.5em !important - } - .jumbo { - display: none; - } - -} - -#main { - display: flex; - flex-direction: column; - align-content: center; - justify-content: center; - align-items: center; - font-size: 30px; - width: 100%; - max-width: 1200px; -} - -video { - width: 95%; -} - -.pre-blob { - display: flex; - background: #333; - border-radius: 50%; - margin: 10px; - height: 45px; - width: 45px; - justify-content: center; - align-items: center; - font-size: 1rem; -} - -.blob { - background: rgba(231, 76, 60,1.0); - box-shadow: 0 0 0 0 rgba(231, 76, 60,1.0); - animation: pulse 2s infinite; -} - -@keyframes pulse { - 0% { - box-shadow: 0 0 0 0px rgba(192, 57, 43, 1); - } - 100% { - box-shadow: 0 0 0 20px rgba(192, 57, 43, 0); - } -} - - -.icon-sup-panel { - display: flex; - flex-direction: row; - justify-content: space-around; - align-items: center; - background: #222; - border-radius: 10px; - padding: 5px; - margin: 5px 0px 5px 0px; -} - -.icon-sub-panel { - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; -} - -#icon-panel { - display: flex; - width: 100%; - justify-content: space-between; - margin-top: 5px; -} - -.icon-sub-sub-panel { - display: flex; - flex-direction: row; -} - -.keys, #key-val { - background: #333; - padding: 2rem; - margin: 5px; - color: #fff; - display: flex; - justify-content: center; - align-items: center; - border-radius: 10px; - cursor: pointer; -} - -#key-val { - pointer-events: none; - background: #fff; - color: #333; - line-height: 1; - font-size: 20px; - flex-direction: column; -} - -.wasd-row { - display: flex; - flex-direction: row; - justify-content: center; - align-items: stretch; -} - -#wasd { - margin: 5px 0px 5px 0px; - background: #222; - border-radius: 10px; - width: 100%; - padding: 20px; - display: flex; - flex-direction: row; - justify-content: space-around; - align-items: stretch; - - user-select: none; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - touch-action: manipulation; -} - -.panel { - display: flex; - justify-content: center; - margin: 5px 0px 5px 0px !important; - background: #222; - border-radius: 10px; - width: 100%; - padding: 10px; -} - -#ping-time, #battery { - font-size: 25px; -} - -#stop { - display: none; -} - -.plan-form { - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; -} - -.details { - display: flex; - padding: 0px 10px 0px 10px; -} diff --git a/tools/bodyteleop/static/poster.png b/tools/bodyteleop/static/poster.png deleted file mode 100644 index ba0e846b22d98ff846b5b54c72a358df6eb1cb94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8297 zcmeHNe@v9;9e?i51BIPptRs~uI_>Bz-DR#qS|YS)doZd8qA7nE@7ly|hO+BF%q{e| zYnx4-QzGp!##HK13t2L5SyP(Z@NS7&LWpUykVrz1{lU_OTp(e|UEJ&4?eqD*@ADR< zsa^ls{@|Z0@B2K@_vh#P`F@|*o^3wl^Av3^kPQ$Z#a(rUcHTl_~@nkUY!F+WzTUYN+x9pBx8k&lRFBGNr z9|`shCU2cDN^RUcd3rE;{HD`*WhhyDV7fJV>m_&k&P4dJ*ld4nwt8Y~aOU}GN4mJP zaI$z}pF7n)5q1R^S~JdIzGH5EY(vYb=qNYrz=O9H4~=;6;8^JJsc86e+?8@;C2|&j zj8BA}vCL2n6vsoV^8U`g2fxJYvcZ~U_qBP|^;X>LN}q}QUFr3mJ<9M?z!?$Hti+_%0!UG;a0x#uX+$)9rUHcBL(P%ieq1d$TB7D$sb!#b`Zv580IFfACt+7pqDO}U2Y0(jSv z?A~wLX3(7)coMl3?^j)y@nd+g+X`dO8w^m=md>&de&R~kc9z9@4v#px`s1GF5eHr~ z#|Tz|xlY%HTQaU#DKdndxhn6UYg_c;Ewi3w?wDI2m5x*CMJj!lNkh~T!s_4z_T*>FroXpWi0 zQwl3$Gk^)9fwRskj$tEwGmzlbrk=oR zq5=Eqc>WufUB~GgEP4;yzk_!;D%s?2CjWxNE3)>b;|1jH6 zdtQe8E*upX2sW4HsOp_T~$sQ}!5Ai+NC3?@{fq~t}sIk_{xm81$0H8n=kXh3# zLOJ&o&Xx1b25kYOQ9hAX1dsSkv65Y`(1LF4?;@lr7JyU+$!;Sah*{Cm0kLC&+r4-3 zVjIq9H(`|?_cKUzW#L2o@g&|R4nh*ilm?3EcOfl|7XiEg6`8u|u@?dsNVyEs2)C0( z`>}mRsN1oX!O77y8t#XGVnqf5!c5N$dC#OJ#tvnFiVA7hFR-lLXE9~#p|I9+Awp^` zg~$wIfzmEW35a#9iQS!8WpPPvH^G!V!*R5y@@kVEP%#glV_6orr$#RQtBiXw&nb8NFXr9kpNYjK%R)p4}ouWEJ3#$ZxQ$smtykgqc(cy=E}Q z>xZ+oEIxsva(KLysYmMYi#-?GDu^jwYc1k|bfaB+mB=g(X(Pi`Gkg zbzc=slQS4_Q;Ag}cPy`ApwA)6oEq#ZkIlBXEw0#0j{1^n!eph)-l-W%OR&{zduA9_ z?L9`z;vlCVyPR0=5;fiZZCa(dE5i(?DGW+=5)X_L>uMRoC|{89zJwSL#FLv7A@QT< zxj&PFh+sh&>(*{11Ud)T<-np7tj^<@vLt-0Td|!9roZi0gu@khV7A58^XzQQh=#Ne zWd@52?81LUG2!rrWUf>cJY2t+?f|q7(}D#BLVx+y-u5+@;Juz60@N( z`?4FKrszuF%m!{2@b{CMNPTkswzDlD{Cxg>57~Dd(@Fxf+LM!scLt`;y`?F49=} z(t$Y;5d8Fm1FQJJVwYKyd|;P^ZoIr!aVY*!+j-e)!kCUcXt!vtKU%7o6A^D>`(T9b zJ3LSQ%jW-Dj)MgH4Cgc^fuXPmcRB%l?n6O}mF-v@#*6IJI3g4MLu$L#$57EtVxv^* z({A5P#qwtAC>H6$lBgpM>eG;I-(pEI zQUshWSMabOv)o*jT-YVG_}buJFho+LTSb9xLoHKextb>4{-Vqm=~OJesd666bb?{XD+!;1fWm2 zg1}~G<>Swak2PjZ9PnUkFHHU{%O&6%~rZn&IbkRW!*I%GrPBR-H + + + + +
+ +""" + +@app.route("/") +def hello_world(): + return index + +last_send_time = time.monotonic() +@app.route("/control//") +def control(x, y): + global last_send_time + x,y = float(x), float(y) + x = max(-1, min(1, x)) + y = max(-1, min(1, y)) + dat = messaging.new_message('testJoystick') + dat.testJoystick.axes = [y,x] + dat.testJoystick.buttons = [False] + pm.send('testJoystick', dat) + last_send_time = time.monotonic() + return "" + +def handle_timeout(): + while 1: + this_time = time.monotonic() + if (last_send_time+0.5) < this_time: + #print("timeout, no web in %.2f s" % (this_time-last_send_time)) + dat = messaging.new_message('testJoystick') + dat.testJoystick.axes = [0,0] + dat.testJoystick.buttons = [False] + pm.send('testJoystick', dat) + time.sleep(0.1) + +def main(): + threading.Thread(target=handle_timeout, daemon=True).start() + app.run(host="0.0.0.0") + +if __name__ == '__main__': + main()