├── .gitignore ├── LICENSE.md ├── LICENSE_THIRD_PARTY.md ├── README.md ├── README_ja.md ├── bin └── data │ ├── camera │ ├── example │ │ ├── GV-USB2_iPad.xml │ │ ├── GV-USB2_iPhone.xml │ │ ├── HD.xml │ │ └── VGA.xml │ └── fpv.xml │ ├── pilots │ ├── pilots.xml │ ├── sample pilot.png │ └── フジヤマFPV.png │ ├── results │ └── .gitkeep │ └── system │ ├── GenShinGothic-Monospace-Bold.ttf │ ├── GenShinGothic-P-Bold.ttf │ ├── background.png │ ├── beep.wav │ ├── beep3.wav │ ├── button_fullscreen.png │ ├── button_quit.png │ ├── button_settings.png │ ├── button_window.png │ ├── cancel.wav │ ├── count.wav │ ├── finish.wav │ ├── logo_large.png │ ├── logo_small.png │ ├── marker.xml │ ├── notify.wav │ └── pilot_icon.png ├── docs ├── HowToBuild.md ├── HowToBuild_en.md ├── OSCAPI.md ├── OSCAPI_en.md ├── gate │ ├── MainGate_TypeA.pdf │ ├── MainGate_TypeA.svg │ ├── MainGate_TypeA_A4.pdf │ ├── MainGate_TypeA_A4.svg │ ├── MainGate_TypeB.pdf │ ├── MainGate_TypeB.svg │ ├── MainGate_TypeC.pdf │ ├── MainGate_TypeC.svg │ ├── MainGate_TypeC_A3.pdf │ ├── MainGate_TypeC_A3.svg │ └── bakcup │ │ ├── MainGate_TypeA.pdf │ │ ├── MainGate_TypeA.svg │ │ ├── MainGate_TypeD.pdf │ │ ├── MainGate_TypeD.svg │ │ └── Marker_Main_0.svg └── img │ ├── argate_multi.png │ ├── argate_single.png │ ├── button_fullscreen.png │ ├── button_quit.png │ ├── button_settings.png │ ├── button_window.png │ ├── install_mac.png │ ├── marker_00_main_a.png │ ├── marker_01_main_b.png │ ├── marker_02_main_c.png │ ├── marker_03_main_d.png │ ├── overview.jpg │ ├── qr_betaflight.png │ └── qr_screen.png ├── of.entitlements ├── src ├── main.cpp ├── ofApp.cpp └── ofApp.h └── test ├── .gitignore ├── osc_debug.js ├── osc_debug_lap.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | #.gitignore is a file which makes git ignore files which should 2 | # not go into version control in the first place 3 | # Questions? See 4 | # http://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files 5 | # http://git-scm.com/docs/gitignore 6 | 7 | ########################### 8 | # ignore generated binaries 9 | # but not the data folder 10 | ########################### 11 | 12 | /bin/* 13 | !/bin/data/ 14 | 15 | ######### 16 | # general 17 | ######### 18 | 19 | [Bb]uild/ 20 | [Oo]bj/ 21 | *.o 22 | [Dd]ebug*/ 23 | [Rr]elease*/ 24 | *.mode* 25 | *.app/ 26 | *.pyc 27 | .svn/ 28 | *.log 29 | 30 | ######################## 31 | # IDE files which should 32 | # be ignored 33 | ######################## 34 | 35 | # XCode 36 | *.pbxuser 37 | *.perspective 38 | *.perspectivev3 39 | *.mode1v3 40 | *.mode2v3 41 | # XCode 4 42 | *.xccheckout 43 | xcuserdata/ 44 | 45 | # Visual Studio 46 | *.sdf 47 | *.opensdf 48 | *.suo 49 | *.pdb 50 | *.ilk 51 | *.aps 52 | ipch/ 53 | 54 | # Eclipse 55 | .metadata 56 | local.properties 57 | .externalToolBuilders 58 | 59 | # Android Studio 60 | .gradle 61 | /local.properties 62 | /.idea/workspace.xml 63 | /.idea/libraries 64 | 65 | ################## 66 | # operating system 67 | ################## 68 | 69 | # Linux 70 | *~ 71 | # KDE 72 | .directory 73 | .AppleDouble 74 | 75 | # OSX 76 | .DS_Store 77 | *.swp 78 | *~.nib 79 | # Thumbnails 80 | ._* 81 | 82 | # Windows 83 | # Image file caches 84 | Thumbs.db 85 | # Folder config file 86 | Desktop.ini 87 | 88 | # Android 89 | .csettings 90 | 91 | ################ 92 | # TVP additional 93 | ################ 94 | 95 | Makefile 96 | Project.xcconfig 97 | addons.make 98 | config.make 99 | openFrameworks-Info.plist 100 | tinyviewplus.xcodeproj/ 101 | bin/data/results/* 102 | !.gitkeep 103 | .vs/ 104 | icon.rc 105 | *.db 106 | *.sln 107 | *vcxproj* 108 | addons/ 109 | bin/data/settings.xml 110 | package-lock.json 111 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Tiny View Plus is distributed under the MIT License. This gives everyone the freedoms to use Tiny View Plus in any context: commercial or non-commercial, public or private, open or closed source. 4 | 5 | --- 6 | 7 | Copyright (c) 2018 t-asano 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /LICENSE_THIRD_PARTY.md: -------------------------------------------------------------------------------- 1 | # Third Party Licenses 2 | 3 | ## openFrameworks 4 | 5 | [http://openframeworks.cc/about/license/](http://openframeworks.cc/about/license/) 6 | 7 | ## ofxTrueTypeFontUC 8 | 9 | [https://github.com/kr15h/ofxTrueTypeFontUC](https://github.com/kr15h/ofxTrueTypeFontUC) 10 | 11 | ## Gen Shin Gothic 12 | 13 | [http://jikasei.me/font/genshin](http://jikasei.me/font/genshin) 14 | 15 | ## ofxAruco 16 | 17 | [https://github.com/chparsons/ofxAruco](https://github.com/chparsons/ofxAruco) 18 | 19 | ## ofxCv 20 | 21 | [https://github.com/kylemcdonald/ofxCv](https://github.com/kylemcdonald/ofxCv) 22 | 23 | ## ofxZxing 24 | 25 | [https://github.com/Iwanaka/ofxZxing](https://github.com/Iwanaka/ofxZxing) 26 | 27 | ## ofxJoystick 28 | 29 | [https://github.com/Lacty/ofxJoystick](https://github.com/Lacty/ofxJoystick) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tiny View Plus 2 | 3 | 日本語版ドキュメントは[こちら](./README_ja.md)。 4 | 5 | Tiny View Plus is a FPV multi-view and lap timing system. It works on PC with UVC compatible FPV receivers. Up to 4 receivers(\*) can be connected. 6 | 7 | ![tinyviewplus](docs/img/overview.jpg) 8 | 9 | **(\*)On Windows, please connect only one receiver to each USB port built in PC.** 10 | 11 | ## Environment 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
OSmacOS (15 Sequoia is recommended)
Windows (11 is recommended)
FPV ReceiverEachine ROTG02
Eachine ROTG01 Pro
Eachine ROTG01
21 | 22 | ## Install 23 | 24 | Attention: We are not responsible for any problems caused by running the application. 25 | 26 | If you want to build from source code, please refer to [this document](docs/HowToBuild_en.md). 27 | 28 | ### macOS 29 | 30 | 1. Download a zip file from [Release page](https://github.com/t-asano/tinyviewplus/releases). 31 | 2. Remove extended file attribute from zip file. 32 | - Run following command on the "Terminal" app. 33 | - ```xattr -c ~/Downloads/tinyviewplus_*_macos64bit.zip``` 34 | 3. Extract zip file. 35 | 4. Place app file in the "Application" folder. 36 | ![install_mac.png](docs/img/install_mac.png) 37 | - If you place it anywhere else, file write functions will not work. 38 | 39 | ### Windows 40 | 41 | 1. Download a zip file from [Release page](https://github.com/t-asano/tinyviewplus/releases). 42 | 2. Extract it and place its contents in the proper place. 43 | 3. Install [Microsoft Visual C++ Redistributable for Visual Studio(vc_redist.x64.exe)](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). 44 | 45 | ## Usage 46 | 47 | ### Launch 48 | 49 | 1. Connect receivers(Up to 4) to computer. 50 | 2. Launch application. 51 | 52 | ### Detection of receivers 53 | 54 | If receivers are not successfully detected, please try following operation. 55 | 56 | 1. Remove all receivers. 57 | 2. If using a USB hub, reconnect it or remove it. 58 | 3. Connect receivers one by one at intervals of several seconds. 59 | 60 | On macOS, if you are using a USB hub and the picture drops, please reduce the number of receivers per USB hub. 61 | 62 | On Windows, if multiple receivers are connected to same USB hub, only one of them may operate. 63 | 64 | ### Keyboard operations 65 | 66 | #### System 67 | 68 | | key | Function | Default value | 69 | | --- | -------------------------------------- | --------------------- | 70 | | N | Set speech language (Japanese/English) | Same as system locale | 71 | | S | Set system statistics (On/Off) | Off | 72 | | H | Display "Settings/Commands" | - | 73 | | I | Initialize settings | - | 74 | 75 | #### Display 76 | 77 | | key | Function | Default value | 78 | | ------------- | ---------------------------------------------------- | -------------- | 79 | | F,Esc | Set fullscreen mode (On/Off) | Off | 80 | | B | Set background image (\*1) | Built-in image | 81 | | T | Set camera view trimming (On/Off) (\*2) | Off | 82 | | E | Set camera frame visibility (On/Off) | Off | 83 | | 1~4 | Set camera 1~4 enhanced view (On/Off) | Off | 84 | | command + 1~4 | Set camera 1~4 visibility (On/Off) [macOS] | On | 85 | | Alt + 1~4 | Set camera 1~4 visibility (On/Off) [Windows] | On | 86 | | L | Set lap history view mode (Off/Inside/Outside) (\*3) | Off | 87 | | Q | Start/Stop QR Code reader for camera label (\*4) | - | 88 | 89 | - (\*1) The background image will be scaled according to the screen. Upper left corner will be displayed in priority. 90 | - (\*2) Camera image will be cropped and displayed as large as possible, when 1 or 3 cameras are connected. 91 | - (\*3) "Outside" will be effective, when 3 cameras are connected. 92 | - (\*4) Sets the characters scanned from the QR Code to the camera label. 93 | 94 | #### Race 95 | 96 | | key | Function | Default value | 97 | | -------------------- | -------------------------------------------------------- | ---------------------- | 98 | | A | Set AR lap timer mode (Normal/Loose/Off) (\*1) | Normal | 99 | | Left/Right,Up/Down,D | Set race duration time (0\~36,000s) and laps (1\~10,000) | 0s (No limit), 10 laps | 100 | | W | Set wait for lap after time limit (On/Off) | Off | 101 | | PgUp/PgDown | Set minimum lap time (1~100s) | 3s | 102 | | G | Set staggered start (On/Off) (\*2) | Off | 103 | | Space | Start/Stop race | - | 104 | | 5~8,Z,/ | Add lap at camera 1~4,1,3 (manual measurement) | - | 105 | | command + 5~8,Z,/ | Delete previos lap at camera 1~4,1,3 [macOS] | - | 106 | | Alt + 5~8,Z,/ | Delete previos lap at camera 1~4,1,3 [Windows] | - | 107 | | R | Display race result (\*3) | - | 108 | | C | Clear race result | - | 109 | 110 | - (\*1) In loose mode, lap time will be measured even if the drone passes outside the gate. 111 | - (\*2) Time measurement starts after passing the first gate. 112 | - (\*3) Race results will be saved under predefined folder when race finish. 113 | - macOS binary: Tiny View Plus.app/Contents/ Resources/data/pilots 114 | - others: data/pilots 115 | 116 | #### Attention 117 | 118 | - When you exit the application, system/race settings will be saved. 119 | - When you exit the application, some display settings will be saved. 120 | - Camera audio is not supported. 121 | 122 | ### Mouse operations 123 | 124 | Some functions can be operated with mouse. 125 | 126 | | Operation | Function | 127 | | ---------------------------------------------------------- | --------------------------- | 128 | | Click camera 1~4 icon | Change icon (\*1) | 129 | | Click camera 1~4 label | Change label (\*2) | 130 | | Click ![settings](docs/img/button_settings.png) button | Display "Settings/Commands" | 131 | | Click ![fullscreen](docs/img/button_fullscreen.png) button | Set fullscreen mode to On | 132 | | Click ![window](docs/img/button_window.png) button | Set fullscreen mode to Off | 133 | | Click ![quit](docs/img/button_quit.png) button | Quit application | 134 | 135 | - (\*1) Camera label will be automatically changed according to changing camera icon. 136 | - The file name of the icon (excluding the extension) will be adopted. 137 | - (\*2) Camera icon will be automatically changed according to changing camera label. 138 | - If {label string}.jpg/png/bmp was found under predefined folder, it will be adopted as an icon image in this priority order. 139 | - macOS binary: Tiny View Plus.app/Contents/ Resources/data/pilots 140 | - others: data/pilots 141 | - If no image file is found, the default icon will be adopted. 142 | - The aspect ratio is forced to 1:1. 143 | 144 | ### Gamepad operations 145 | 146 | Some functions can also be operated with gamepad. Up to 4 gamepads can be used simultaneously. 147 | 148 | | Button | Function | 149 | | ------- | ------------------------------------------ | 150 | | 1~4 | Add lap at camera 1~4 (manual measurement) | 151 | | 5 + 1~4 | Delete previos lap at camera 1~4 | 152 | 153 | ### QR Code for label setting 154 | 155 | You can set the camera label by the QR Code. 156 | 157 | ![qr_screen.png](docs/img/qr_screen.png) 158 | 159 | You can use Google Charts API to create QR Code. An example of URL is as follows. 160 | 161 | [https://chart.apis.google.com/chart?cht=qr&chs=500x500&chl=TinyViewPlus](https://chart.apis.google.com/chart?cht=qr&chs=500x500&chl=TinyViewPlus) 162 | 163 | It is convenient to embed the QR Code in the OSD. An example of an image for the Betaflight is as follows. 164 | 165 | ![qr_betaflight.png](docs/img/qr_betaflight.png) 166 | 167 | \* "QR Code" is a registered trademark of DENSO WAVE INCORPORATED. 168 | 169 | ### AR lap timer 170 | 171 | You can measure the lap time by using AR marker. 172 | 173 | ![argate_single.png](docs/img/argate_single.png) 174 | ![argate_multi.png](docs/img/argate_multi.png) 175 | 176 | Please place 8 or more markers around the gate. Also make sure that the top of the marker faces the center of the gate. Following four types of markers are supported. It does not matter if only one type is placed as shown above. 177 | 178 | - [marker_00_main_a.png](docs/img/marker_00_main_a.png) 179 | - [marker_01_main_b.png](docs/img/marker_01_main_b.png) 180 | - [marker_02_main_c.png](docs/img/marker_02_main_c.png) 181 | - [marker_03_main_d.png](docs/img/marker_03_main_d.png) 182 | 183 | The size of the marker should be 120-150mm per side. Larger marker will be suitable for higher speed range. If marker recognition is not successful, please try increasing the size of the marker or placing them in a brighter place. 184 | 185 | Following are gate design prototypes. 186 | 187 | - Normal gate : [Whole (A0)](docs/gate/MainGate_TypeA.pdf) [Part (A4)](docs/gate/MainGate_TypeA_A4.pdf) 188 | - Gate for high speed : [Whore (A0)](docs/gate/MainGate_TypeC.pdf) [Part (A3)](docs/gate/MainGate_TypeC_A3.pdf) 189 | - [Others](docs/gate) 190 | 191 | Lap time will be measured only during the race. After detecting two or more correctly oriented markers simultaneously, when the marker disappears from the screen, lap time will be confirmed. However, if the direction of the last displayed marker is incorrect, the measurement will be canceled. 192 | 193 | Depending on the environment, recognition processing of markers might be heavy. In that case, please disable the function. 194 | 195 | ### Combination of automatic and manual measurement 196 | 197 | When automatic and manual measurement are used together, the one with earlier timing will be adopted and recorded. The one with later timing will be rejected and not be recorded. 198 | 199 | However, if the interval between the two is equal to or greater than the minimum lap time setting, it will be considered as individual laps, both will be adopted and will be recorded. 200 | 201 | ## OSC API 202 | 203 | Tiny View Plus can be controlled and monitored by OSC protocol. Detailed information is [here](docs/OSCAPI_en.md). 204 | 205 | ## License 206 | 207 | Tiny View Plus is distributed under the MIT License. This gives everyone the freedoms to use Tiny View Plus in any context: commercial or non-commercial, public or private, open or closed source. Please see [LICENSE.md](LICENSE.md) and [LICENSE\_THIRD\_PARTY.md](LICENSE_THIRD_PARTY.md) for details. -------------------------------------------------------------------------------- /README_ja.md: -------------------------------------------------------------------------------- 1 | # Tiny View Plus 2 | 3 | The English version is [here](./README.md). 4 | 5 | Tiny View Plusはラップ計測に対応したFPVマルチビューアーです。UVC対応のFPV受信機をPCに接続して使用します。受信機は4台まで(※)接続できます。 6 | 7 | ![tinyviewplus](docs/img/overview.jpg) 8 | 9 | **(※)Windowsの場合、USBハブに複数の受信機を接続すると正しく動作しないことがあります。USBポート1つにつき、受信機1台のみを接続してください。ただし、PC内部でハブが接続されている場合もあり、その場合には正しく動作しません。** 10 | 11 | ## 動作環境 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
OSmacOS (15 Sequoia推奨)
Windows (11推奨)
受信機Eachine ROTG02
Eachine ROTG01 Pro
Eachine ROTG01
21 | 22 | 冒頭の写真の例では、USBハブ(C-A)とUSBケーブル(A-microB)を別途用意しています。この場合、ROTG付属のUSBケーブル(OTG用microB-microB)は使用しません。 23 | 24 | ## インストール 25 | 26 | バイナリの作成にあたっては細心の注意を払っていますが、アプリを実行することで起こる不具合については、一切責任を負いません。 27 | 28 | ソースコードからビルドする場合は、[こちらのドキュメント](docs/HowToBuild.md)を参照してください。 29 | 30 | ### macOSの場合 31 | 32 | 1. [リリースページ](https://github.com/t-asano/tinyviewplus/releases)よりzipファイルをダウンロード 33 | 2. zipファイルに付いている拡張属性を削除 34 | - 以下のコマンドをmacOSの「ターミナル」で実行 35 | - ```xattr -c ~/Downloads/tinyviewplus_*_macos64bit.zip``` 36 | 3. zipファイルを展開 37 | 4. アプリ本体を「アプリケーション」フォルダの下に配置 38 | ![install_mac.png](docs/img/install_mac.png) 39 | - 別の場所に配置すると、設定保存機能などが正しく動作しません。 40 | 41 | ### Windowsの場合 42 | 43 | 1. [リリースページ](https://github.com/t-asano/tinyviewplus/releases)よりzipファイルをダウンロード 44 | 2. zipファイルを展開して適当な場所に配置 45 | 3. [Visual Studio 用 Microsoft Visual C++ 再頒布可能パッケージ(vc_redist.x64.exe)](https://support.microsoft.com/ja-jp/help/2977003/the-latest-supported-visual-c-downloads)をインストール 46 | 47 | ## 使い方 48 | 49 | ### 起動 50 | 51 | 1. コンピューターに受信機(4台まで)を接続 52 | 2. アプリ本体をダブルクリックして起動 53 | 54 | ### 受信機の検出 55 | 56 | 受信機がうまく検出されない場合は、以下をお試し下さい。 57 | 58 | 1. 受信機を全て外す 59 | 2. USBハブ使用の場合はそれを接続し直す、または撤去する 60 | 3. 受信機を一台ずつ数秒間隔で接続 61 | 62 | macOSの場合、USBハブを使用していて映像がコマ落ちするようなら、USBハブ1台あたりの受信機の数を2台以下を目安に減らしてください。 63 | 64 | Windowsの場合、USBハブに複数の受信機を接続した場合に、そのうち1台しか動作しないことがあります。この場合、USBハブを経由せずに接続すれば改善するかもしれません。 65 | 66 | ### キーボードによる操作 67 | 68 | #### システム 69 | 70 | | キー | 機能 | 初期値 | 71 | | --- | ------------------- | --------- | 72 | | N | 音声読み上げ言語の設定(日本語/英語) | システム設定に従う | 73 | | S | システム統計の設定(オン/オフ) | オフ | 74 | | H | ヘルプ(設定/コマンド)の表示 | - | 75 | | I | 設定の初期化 | - | 76 | 77 | #### 表示 78 | 79 | | キー | 機能 | 初期値 | 80 | | ------------- | -------------------------------- | -------- | 81 | | F,Esc | フルスクリーン表示の設定(オン/オフ) | オフ | 82 | | B | 背景画像の設定(※1) | アプリ内蔵の画像 | 83 | | T | カメラのトリミングの設定(オン/オフ)(※2) | オフ | 84 | | E | カメラ枠表示の設定(オン/オフ) | オフ | 85 | | 1~4 | カメラ1~4の拡大表示の設定(オン/オフ) | オフ | 86 | | command + 1~4 | カメラ1~4の表示の設定(オン/オフ) [macOS] | オン | 87 | | Alt + 1~4 | カメラ1~4の表示の設定(オン/オフ) [Windows] | オン | 88 | | L | レース中のラップ履歴表示モードの設定(オフ/内側/外側)(※3) | オフ | 89 | | Q | QRコードリーダーの開始/停止(※4) | - | 90 | 91 | - (※1)背景画像は、縦横比を維持したまま画面に合わせて拡大縮小され、左上隅が優先表示されます。 92 | - (※2)カメラが1台または3台の場合に、映像の一部をトリミングして大きく表示します。 93 | - (※3)カメラが3台の場合に「外側」が設定されていると、カメラ映像の外側にラップ履歴が表示されます。 94 | - (※4)QRコードから読み取った文字列を、カメラのラベルに設定します。 95 | 96 | #### レース 97 | 98 | | キー | 機能 | 初期値 | 99 | | -------------------- | -------------------------------------- | ------------ | 100 | | A | ARラップタイマーのモードの設定(ノーマル/ルーズ/オフ)(※1) | オン | 101 | | Left/Right,Up/Down,D | レースの制限時間(0\~36,000秒)、周回数(1\~10,000)の設定 | 0秒(制限なし)、10周 | 102 | | W | 制限時間経過後のラップ計測待ちの設定(オン/オフ) | オフ | 103 | | PgUp/PgDown | 最小ラップタイムの設定(1~100秒) | 3秒 | 104 | | G | 時差スタートの設定(オン/オフ)(※2) | オフ | 105 | | Space | レースの開始/終了 | - | 106 | | 5~8,Z,/ | カメラ1~4,1,3のラップの追加(手動計測) | - | 107 | | command + 5~8,Z,/ | カメラ1~4,1,3の直前ラップの削除 [macOS] | - | 108 | | Alt + 5~8,Z,/ | カメラ1~4,1,3の直前ラップの削除 [Windows] | - | 109 | | R | レースの結果の表示(※3) | - | 110 | | C | レースの結果の消去 | - | 111 | 112 | - (※1)ルーズモードでは、ゲートの外側を通過しても計測対象となります。 113 | - (※2)最初のゲートを通過した後にタイム計測を開始します。 114 | - (※3)レースの結果は、レース終了時に既定フォルダ内へも出力されます。 115 | - macOSバイナリ版: Tiny View Plus.app/Contents/Resources/data/results 116 | - それ以外: data/results 117 | 118 | #### ご注意 119 | 120 | - アプリを終了すると、システムとレースの設定および表示の一部が保存されます。 121 | - カメラの音声は出力されません。 122 | 123 | ### マウスによる操作 124 | 125 | 一部の機能は、マウスで操作できます。 126 | 127 | | 操作 | 機能 | 128 | | ------------------------------------------------------ | --------------- | 129 | | カメラ1~4のアイコンをクリック | アイコンの変更(※1) | 130 | | カメラ1~4のラベルをクリック | ラベルの変更(※2) | 131 | | ![settings](docs/img/button_settings.png) ボタンをクリック | ヘルプ(設定/コマンド)の表示 | 132 | | ![fullscreen](docs/img/button_fullscreen.png) ボタンをクリック | フルスクリーン表示のオン | 133 | | ![window](docs/img/button_window.png) ボタンをクリック | フルスクリーン表示のオフ | 134 | | ![quit](docs/img/button_quit.png) ボタンをクリック | アプリの終了 | 135 | 136 | - (※1)カメラのアイコンを変更すると、ラベルが自動的に変更されます。 137 | - アイコンのファイル名(拡張子を除く)が採用されます。 138 | - (※2)カメラのラベルを変更すると、アイコンが自動的に変更されます。 139 | - 既定フォルダ内に、ラベル文字列.jpg/png/bmp という画像ファイルが見つかると、この優先順でアイコン画像として採用されます。 140 | - macOSバイナリ版: Tiny View Plus.app/Contents/Resources/data/pilots 141 | - それ以外: data/pilots 142 | - 画像ファイルが見つからない場合は、デフォルトアイコンが採用されます。 143 | - 縦横比は強制的に1:1となります。 144 | 145 | ### ゲームパッドによる操作 146 | 147 | 一部の機能は、ゲームパッドでも操作もできます。ゲームパッドは、最大4台まで同時に利用できます。 148 | 149 | | ボタン | 機能 | 150 | | ------------- | ------------------- | 151 | | ボタン1~4 | カメラ1~4のラップの追加(手動計測) | 152 | | ボタン5 + ボタン1~4 | カメラ1~4の直前ラップの削除 | 153 | 154 | ### QRコードによるラベル設定 155 | 156 | QRコードを使用して、カメラのラベルを設定できます。 157 | 158 | ![qr_screen.png](docs/img/qr_screen.png) 159 | 160 | QRコードを作成するには、Google Charts APIが利用できます。以下は、QRコードを作成するためのURLの例です。 161 | 162 | [https://chart.apis.google.com/chart?cht=qr&chs=500x500&chl=TinyViewPlus](https://chart.apis.google.com/chart?cht=qr&chs=500x500&chl=TinyViewPlus) 163 | 164 | QRコードをOSDに組み込んでおくと便利です。以下は、Betaflight用のロゴ画像の例です。 165 | 166 | ![qr_betaflight.png](docs/img/qr_betaflight.png) 167 | 168 | ※QRコードは(株)デンソーウェーブの登録商標です。 169 | 170 | ### ARマーカーによるラップ計測 171 | 172 | ARマーカーを利用して、ラップタイムを計測できます。 173 | 174 | ![argate_single.png](docs/img/argate_single.png) 175 | ![argate_multi.png](docs/img/argate_multi.png) 176 | 177 | マーカーは8個以上を目安として、ゲートの周囲に配置してください。またその際に、マーカーの上側がゲートの中央を向くようにしてください。以下の4種類のマーカーに対応していますが、上の図のように1種類のみを配置する形でも構いません。 178 | 179 | - [marker_00_main_a.png](docs/img/marker_00_main_a.png) 180 | - [marker_01_main_b.png](docs/img/marker_01_main_b.png) 181 | - [marker_02_main_c.png](docs/img/marker_02_main_c.png) 182 | - [marker_03_main_d.png](docs/img/marker_03_main_d.png) 183 | 184 | マーカーのサイズは1辺120~150mmを目安として、通過スピードに応じて調整してください。ハイスピードレースにおいては、より大きなマーカーが適しています。マーカーの認識がうまくいかない場合は、マーカーを大きくしたり、より明るい場所に設置すると、改善するかもしれません。 185 | 186 | 以下は、試作中のゲートの印刷データです。ご活用ください。 187 | 188 | - 標準ゲート : [全体 (A0)](docs/gate/MainGate_TypeA.pdf) [分割 (A4)](docs/gate/MainGate_TypeA_A4.pdf) 189 | - 高速レース用ゲート : [全体 (A0)](docs/gate/MainGate_TypeC.pdf) [分割 (A3)](docs/gate/MainGate_TypeC_A3.pdf) 190 | - [その他](docs/gate) 191 | 192 | ラップタイムの計測は、レース中にのみ行われます。同時に2個以上の正しい向きのマーカーを検出した後、画面からマーカーが消えたタイミングでラップタイムが確定します。ただし、最後に映っていたマーカーの向きが正しくない(ゲートの外側を通った等の)場合は、計測の対象外となります。 193 | 194 | 環境によっては、マーカーの認識処理が重く、動作に支障があるかもしれません。その場合は、機能を無効化してください。 195 | 196 | ### 自動計測と手動計測の併用 197 | 198 | 自動計測と手動計測を併用した場合、タイミングが早い方が採用され、記録に残ります。タイミングが遅い方は却下され、記録に残りません。ただし、両者の間隔が最小ラップタイム設定値以上であれば、別々のラップとみなされ、両者ともに採用され、記録に残ります。 199 | 200 | ## OSCによる制御 201 | 202 | OSCプロトコルによって、外部からの制御と監視が可能です。詳しくは[こちら](docs/OSCAPI.md)をご覧ください。 203 | 204 | ## ライセンス 205 | 206 | Tiny View Plus is distributed under the MIT License. This gives everyone the freedoms to use Tiny View Plus in any context: commercial or non-commercial, public or private, open or closed source. Please see [LICENSE.md](LICENSE.md) and [LICENSE\_THIRD\_PARTY.md](LICENSE_THIRD_PARTY.md) for details. -------------------------------------------------------------------------------- /bin/data/camera/example/GV-USB2_iPad.xml: -------------------------------------------------------------------------------- 1 | 2 | GV-USB2 3 | iPad(4:3 in squeezed 16:9) 4 | 5 | 704 6 | 480 7 | 8 | 9 | 82 10 | 0 11 | 540 12 | 480 13 | 14 | 15 | 4:3 16 | 17 | -------------------------------------------------------------------------------- /bin/data/camera/example/GV-USB2_iPhone.xml: -------------------------------------------------------------------------------- 1 | 2 | GV-USB2 3 | iPhone(16:9 in squeezed 16:9) 4 | 5 | 704 6 | 480 7 | 8 | 9 | 0 10 | 0 11 | 704 12 | 480 13 | 14 | 15 | 16:9 16 | 17 | -------------------------------------------------------------------------------- /bin/data/camera/example/HD.xml: -------------------------------------------------------------------------------- 1 | 2 | HD Device Name 3 | 16:9 4 | 5 | 1280 6 | 720 7 | 8 | 9 | 0 10 | 0 11 | 1280 12 | 720 13 | 14 | 15 | 16:9 16 | 17 | -------------------------------------------------------------------------------- /bin/data/camera/example/VGA.xml: -------------------------------------------------------------------------------- 1 | 2 | VGA Device Name 3 | 4:3 4 | 5 | 640 6 | 480 7 | 8 | 9 | 0 10 | 0 11 | 640 12 | 480 13 | 14 | 15 | 4:3 16 | 17 | -------------------------------------------------------------------------------- /bin/data/camera/fpv.xml: -------------------------------------------------------------------------------- 1 | 2 | GV-USB2 3 | squeezed 16:9 4 | 5 | 704 6 | 480 7 | 8 | 9 | 0 10 | 0 11 | 704 12 | 480 13 | 14 | 15 | 16:9 16 | 17 | -------------------------------------------------------------------------------- /bin/data/pilots/pilots.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/pilots/pilots.xml -------------------------------------------------------------------------------- /bin/data/pilots/sample pilot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/pilots/sample pilot.png -------------------------------------------------------------------------------- /bin/data/pilots/フジヤマFPV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/pilots/フジヤマFPV.png -------------------------------------------------------------------------------- /bin/data/results/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/results/.gitkeep -------------------------------------------------------------------------------- /bin/data/system/GenShinGothic-Monospace-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/GenShinGothic-Monospace-Bold.ttf -------------------------------------------------------------------------------- /bin/data/system/GenShinGothic-P-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/GenShinGothic-P-Bold.ttf -------------------------------------------------------------------------------- /bin/data/system/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/background.png -------------------------------------------------------------------------------- /bin/data/system/beep.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/beep.wav -------------------------------------------------------------------------------- /bin/data/system/beep3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/beep3.wav -------------------------------------------------------------------------------- /bin/data/system/button_fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/button_fullscreen.png -------------------------------------------------------------------------------- /bin/data/system/button_quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/button_quit.png -------------------------------------------------------------------------------- /bin/data/system/button_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/button_settings.png -------------------------------------------------------------------------------- /bin/data/system/button_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/button_window.png -------------------------------------------------------------------------------- /bin/data/system/cancel.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/cancel.wav -------------------------------------------------------------------------------- /bin/data/system/count.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/count.wav -------------------------------------------------------------------------------- /bin/data/system/finish.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/finish.wav -------------------------------------------------------------------------------- /bin/data/system/logo_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/logo_large.png -------------------------------------------------------------------------------- /bin/data/system/logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/logo_small.png -------------------------------------------------------------------------------- /bin/data/system/marker.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 4 | 4 5 | 4 6 | "1011010100110010" 7 | "0000111110011010" 8 | "0011001100101101" 9 | "1001100101000110" 10 | 11 | -------------------------------------------------------------------------------- /bin/data/system/notify.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/notify.wav -------------------------------------------------------------------------------- /bin/data/system/pilot_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/bin/data/system/pilot_icon.png -------------------------------------------------------------------------------- /docs/HowToBuild.md: -------------------------------------------------------------------------------- 1 | # Tiny View Plusのビルド 2 | 3 | ## 開発環境のセットアップ 4 | 5 | ### macOSの場合 6 | 7 | 1. Xcode 16をインストールする 8 | 2. openFrameworks 0.12.0をインストールする 9 | - [openFrameworks for osx (zipファイル)](https://openframeworks.cc/download/)をダウンロードする 10 | - 拡張属性を取り除く 11 | - $ xattr -cr of\_\*\_osx_release.zip 12 | - 適当な場所に展開する 13 | 14 | ### Windowsの場合 15 | 16 | 1. Visual Studioをインストールする 17 | - [こちらのドキュメント](https://openframeworks.cc/setup/vs/)を参考とする 18 | - 「openFrameworks plugin for Visual Studio」は実施しない 19 | 2. openFrameworks 0.11.2をインストールする 20 | - [openFrameworks for visual studio (zipファイル)](https://openframeworks.cc/download/)をダウンロードする 21 | - 適当な場所に展開する 22 | 3. [Git for Windows](https://gitforwindows.org)をインストールする 23 | - これに含まれるGit Bashを使って、GitHubからのファイルの取得や、ローカルでのファイル操作を行うことになる 24 | 25 | ## プロジェクトの作成 26 | 27 | 1. 必要なアドオンをインストールしておく 28 | 29 | ```bash 30 | $ cd addons/ 31 | $ git clone -b fix-of_v0.10 https://github.com/t-asano/ofxTrueTypeFontUC.git 32 | $ git clone https://github.com/t-asano/ofxAruco.git 33 | $ git clone https://github.com/kylemcdonald/ofxCv.git 34 | $ git clone https://github.com/t-asano/ofxZxing.git 35 | $ git clone https://github.com/t-asano/ofxJoystick.git 36 | ``` 37 | 38 | 2. プロジェクトジェネレーターで、以下のアドオンを含むプロジェクトを作成する。プロジェクト名は「tinyviewplus」とする。 39 | 40 | - ofxOsc 41 | - ofxTrueTypeFontUC 42 | - ofxAruco 43 | - ofxCv 44 | - ofxOpenCv 45 | - ofxPoco 46 | - ofxZxing 47 | - ofxJoystick 48 | - ofxXmlSettings 49 | 50 | 3. 作成したプロジェクトに、Tiny View Plusのファイル一式をマージする 51 | 52 | ```bash 53 | $ cd apps/myApps 54 | $ mv tinyviewplus tvptemp 55 | $ git clone https://github.com/t-asano/tinyviewplus.git 56 | $ cp tvptemp/* tinyviewplus/ 57 | $ cp -r tvptemp/*.xcodeproj tinyviewplus/ # macOSの場合のみ 58 | $ rm -r tvptemp 59 | ``` 60 | 61 | ## ビルドの設定 62 | 63 | ### macOSの場合 64 | 65 | 1. プロジェクトファイル(tinyviewplus.xcodeproj)をXcodeで開く 66 | 67 | ### Windowsの場合 68 | 69 | 1. ソリューションファイル(tinyviewplus.sln)をVisualStudioで開く 70 | 71 | 2. ソースファイルの文字コードを固定する 72 | 73 | - tinyviewplusプロジェクトのプロパティを開く 74 | - [構成プロパティ] -> [C/C++] -> [コマンドライン] と進む 75 | - 「全ての構成」「すべてのプラットフォーム」に対して、「追加のオプション」として「/source-charset:utf-8」を追加する 76 | 77 | 3. アプリ起動時にコンソールが表示されるのを避ける 78 | 79 | - tinyviewplusプロジェクトのプロパティを開く 80 | - [構成プロパティ] -> [リンカ] -> [システム] と進む 81 | - 「全ての構成」「すべてのプラットフォーム」に対して、「サブシステム」として「Windows (/SUBSYSTEM:WINDOWS)」を指定する 82 | - [構成プロパティ] -> [リンカ] -> [詳細設定] と進む 83 | - 「全ての構成」「すべてのプラットフォーム」に対して、「エントリポイント」として「mainCRTStartup」を指定する 84 | 85 | 4. 文字化けを防ぐ 86 | 87 | - openFrameworks の ofSystemUtils.cpp を改造する 88 | 89 | ```cpp 90 | static void narrow(const std::wstring &src, std::string &dest) { 91 | setlocale(LC_CTYPE, ""); 92 | char *mbs = new char[src.length() * MB_CUR_MAX + 1]; 93 | wcstombs(mbs, src.c_str(), src.length() * MB_CUR_MAX + 1); 94 | dest = mbs; 95 | delete[] mbs; 96 | } 97 | 98 | std::string convertWideToNarrow( const wchar_t *s, char dfault = '?', const std::locale& loc = std::locale() ) 99 | { 100 | #if 0 101 | std::ostringstream stm; 102 | while (*s != L'\0') { 103 | stm << std::use_facet< std::ctype >(loc).narrow(*s++, dfault); 104 | } 105 | return stm.str(); 106 | #else 107 | std::wstring wstr(s); 108 | std::string ret; 109 | narrow(wstr, ret); 110 | return ret; 111 | #endif 112 | } 113 | ``` 114 | 115 | ## ビルドと起動 116 | 117 | ### macOSの場合 118 | 119 | 1. ビルドターゲットを「tinyviewplus Release」に設定する 120 | 2. [Product] -> [Build] でビルドする 121 | 3. ビルドが成功したら [Product] -> [Run] で起動する 122 | 123 | ### Windowsの場合 124 | 125 | 1. ビルドターゲットを「Release」「x64」に設定する 126 | 2. [ビルド] -> [ソリューションのビルド] でビルドする 127 | 3. ビルドが成功したら [デバッグ] -> [デバッグの開始] で起動する 128 | 129 | ## アップデート 130 | 131 | 1. Tiny View Plusとアドオンを更新する 132 | 133 | ```bash 134 | $ cd apps/myApps/tinyviewplus 135 | $ git pull 136 | $ cd ../../../addons/ADDON_NAME 137 | $ git pull 138 | ``` 139 | 140 | 2. アドオンを追加する(必要な場合のみ) 141 | 142 | - Gitコマンドで新規のアドオンを取得する 143 | - プロジェクトジェネレーターでアドオンを追加する 144 | 145 | 以上 -------------------------------------------------------------------------------- /docs/HowToBuild_en.md: -------------------------------------------------------------------------------- 1 | # How to build Tiny View Plus 2 | 3 | The English version is not available yet. The Japanese version is [here](HowToBuild.md). -------------------------------------------------------------------------------- /docs/OSCAPI.md: -------------------------------------------------------------------------------- 1 | # OSCによるTiny View Plusの制御と監視 2 | 3 | Tiny View Plusは、OSCプロトコルによって、外部からの制御と監視が可能です。 4 | 5 | ## Tiny View Plusの制御(受信側) 6 | 7 | UDP4000番ポートでOSCパケットを受信します。 8 | 9 | ### カメラの拡大表示 10 | 11 | /v1/camera/{id}/solo {switch} 12 | 13 | - パラメーター 14 | - id ... カメラID(1~4) 15 | - switch ... "on" または "off" 16 | - 例: カメラ1を拡大表示する 17 | - /v1/camera/1/solo "on" 18 | 19 | ### カメラの表示/非表示 20 | 21 | /v1/camera/{id}/display {switch} 22 | 23 | - パラメーター 24 | - id ... カメラID(1~4) 25 | - switch ... "on" または "off" 26 | - 例: カメラ1を非表示とする 27 | - /v1/camera/1/display "off" 28 | 29 | ### カメラのラベルの変更 30 | 31 | /v1/camera/{id}/label {label} 32 | 33 | - パラメーター 34 | - id ... カメラID(1~4) 35 | - label ... 任意の文字列(パイロット名など) 36 | - 例: カメラ2のラベルを"Whooper2"とする 37 | - /v1/camera/2/label "Whooper 2" 38 | 39 | ラベルの変更と連動して、アイコンも自動的に変更されます。 40 | 41 | - macOSバイナリの場合は "Tiny View Plus.app/Contents/Resources/data/pilots" フォルダの下、それ以外の場合は "data/pilots" フォルダの下に、{label}.png または {label}.jpg という画像ファイルが見つかると、この優先順でアイコン画像として採用します 42 | - 画像ファイルが見つからない場合は、デフォルトアイコンが採用されます 43 | - 縦横比は強制的に1:1となります 44 | 45 | ### ラップタイムの設定 46 | 47 | /v1/camera/{id}/laptime {time} 48 | 49 | - パラメーター 50 | - id ... カメラID(1~4) 51 | - time ... ラップタイム(秒) 52 | - 例: カメラ3のラップタイムを128秒64とする 53 | - /v1/camera/3/laptime 128.64 54 | 55 | ### ラップの追加と削除 56 | 57 | /v1/camera/{id}/lap {command} 58 | 59 | - パラメーター 60 | - id ... カメラID(1~4) 61 | - command ... "add"(追加)または"del"(削除) 62 | - 例: カメラ3のラップを追加する 63 | - /v1/camera/3/lap "add" 64 | 65 | ### 音声読み上げ 66 | 67 | /v1/speech/{language}/say {text} 68 | 69 | - パラメーター 70 | - language ... "en"(英語)または"jp"(日本語) 71 | - text ... 読み上げ文 72 | - 例: 日本語で"ドローンで遊ぼう"と読み上げる 73 | - /v1/speeech/jp/say "ドローンで遊ぼう" 74 | 75 | ## Tiny View Plusの監視(送信側) ※実験的な機能 76 | 77 | "settings.xml"で指定されたホスト・ポートへOSCパケットを送信します。 78 | 79 | ```xml 80 | 81 | 1 82 | 127.0.0.1 83 | 4001 84 | 85 | ``` 86 | 87 | "settings.xml"は初回起動時に自動生成されます。この機能を有効にするには、Tiny View Plusを終了させた状態で、"enabled"に1を設定してください。無効にするには、0を設定してください。 88 | 89 | ### システム情報の通知 90 | 91 | /v1/system/info {info} 92 | 93 | - パラメーター 94 | - info ... システム情報 95 | - 例: "hello"を通知する 96 | - /v1/system/info "hello" 97 | 98 | ### レースイベントの通知 99 | 100 | /v1/race/event {event} 101 | 102 | - パラメーター 103 | - event ... "started"または"finished" 104 | - 例: レースの開始を通知する 105 | - /v1/race/event "started" 106 | 107 | ### カメラのラベルの通知 108 | 109 | /v1/camera/{id}/label {label} 110 | 111 | - パラメーター 112 | - id ... カメラID(1~4) 113 | - label ... カメラのラベル(パイロット名など) 114 | - 例: カメラ2のラベルを通知する 115 | - /v1/camera/2/label "Whooper 2" 116 | 117 | レース開始時およびラベル変更時に通知します。 118 | 119 | ### ラップの通知 120 | 121 | /v1/camera/{id}/lap {lapnum} {laptime} {label} 122 | 123 | - パラメーター 124 | - id ... カメラID(1~4) 125 | - lapnum ... ラップ番号 126 | - laptime ... ラップタイム(秒) 127 | - label ... カメラのラベル(パイロット名など) 128 | - 例: カメラ3のラップを通知する(ラップ5、10.2秒) 129 | - /v1/camera/3/lap 5 10.2 "Whooper 3" 130 | 131 | ### ラップの削除の通知 132 | 133 | /v1/camera/{id}/lapdel {lapnum} 134 | 135 | - パラメーター 136 | - id ... カメラID(1~4) 137 | - lapnum ... ラップ番号 138 | - 例: カメラ3のラップの削除を通知する(ラップ5) 139 | - /v1/camera/3/lapdel 5 140 | 141 | ### レース結果の通知 142 | 143 | /v1/camera/{id}/result {label} {pos} {laps} {bestlap} {totaltime} 144 | 145 | - パラメーター 146 | - id ... カメラID(1~4) 147 | - label ... カメラのラベル(パイロット名など) 148 | - pos ... 順位 149 | - laps ... ラップ数 150 | - bestlap ... ベストラップ(秒) 151 | - totaltime ... 総合タイム(秒) 152 | - 例: カメラ1のレース結果を通知する(1位、10周、5.43秒、62.13秒) 153 | - /v1/camera/1/lap "Whooper 1" 1 10 5.43 62.13 154 | 155 | レース終了時に通知します。 156 | -------------------------------------------------------------------------------- /docs/OSCAPI_en.md: -------------------------------------------------------------------------------- 1 | # OSC API for Tiny View Plus 2 | 3 | Tiny View Plus can be controlled and monitored by OSC protocol. 4 | 5 | ## Controlling(receiver) 6 | 7 | It receives OSC packet at UDP port 4000. 8 | 9 | ### Set camera enhanced view on / off 10 | 11 | /v1/camera/{id}/solo {switch} 12 | 13 | - Parameters 14 | - id ... Camera ID(1~4) 15 | - switch ... "on" or "off" 16 | - Example: Camera 1 enhanced view on 17 | - /v1/camera/1/solo "on" 18 | 19 | ### Set camera display on / off 20 | 21 | /v1/camera/{id}/display {switch} 22 | 23 | - Parameters 24 | - id ... Camera ID(1~4) 25 | - switch ... "on" or "off" 26 | - Example: Camera 1 off 27 | - /v1/camera/1/display "off" 28 | 29 | ### Set camera label 30 | 31 | /v1/camera/{id}/label {label} 32 | 33 | - Parameters 34 | - id ... Camera ID(1~4) 35 | - label ... Any string (such as pilot name) 36 | - Example: Set the label of camera 2 to "Whooper 2" 37 | - /v1/camera/2/label "Whooper 2" 38 | 39 | Camera icon is also automatically changed in conjunction with the camera label change. 40 | 41 | - If {label string}.png or {label string}.jpg was found under "Tiny View Plus.app / Contents / Presents / data / pilots" folder (on macOS binary), otherwise under the "data / pilots" folder, it is adopted as an icon image in this priority order. 42 | - If no image file is found, the default icon will be adopted. 43 | - The aspect ratio is forced to 1:1. 44 | 45 | ### Set laptime 46 | 47 | /v1/camera/{id}/laptime {time} 48 | 49 | - Parameters 50 | - id ... Camera ID(1~4) 51 | - time ... lap time(seconds) 52 | - Example: Set the lap time of camera 3 to 128.64 seconds 53 | - /v1/camera/3/laptime 128.64 54 | 55 | ### Add/Delete lap 56 | 57 | /v1/camera/{id}/lap {command} 58 | 59 | - Parameters 60 | - id ... Camera ID(1~4) 61 | - command ... "add" or "del" 62 | - Example: Add lap of camera 3 63 | - /v1/camera/3/lap "add" 64 | 65 | ### Speech synthesis 66 | 67 | /v1/speech/{language}/say {text} 68 | 69 | - Parameters 70 | - language ... "en"(English) or "jp"(Japanese) 71 | - text ... sentence to speak 72 | - Example: Say "We can fly!" in English 73 | - /v1/speeech/en/say "We can fly!" 74 | 75 | ## Monitoring(sender) ※experimental 76 | 77 | It sends OSC packet to the host/port specified in "settings.xml". 78 | 79 | ```xml 80 | 81 | 1 82 | 127.0.0.1 83 | 4001 84 | 85 | ``` 86 | 87 | Set "enabled" to 1 to enable this feature. Set to 0 to disable. 88 | 89 | ### System information notification 90 | 91 | /v1/system/info {info} 92 | 93 | - Parameters 94 | - info ... System information 95 | - Example: "Hello" 96 | - /v1/system/info "hello" 97 | 98 | ### Race event notifiacation 99 | 100 | /v1/race/event {event} 101 | 102 | - Parameters 103 | - event ... "started" or "finished" 104 | - Example: Race has started 105 | - /v1/race/event "started" 106 | 107 | ### Camera label notification 108 | 109 | /v1/camera/{id}/label {label} 110 | 111 | - Parameters 112 | - id ... Camera ID(1~4) 113 | - label ... Camera label 114 | - Example: Notify the label of camera 2 115 | - /v1/camera/2/label "Whooper 2" 116 | 117 | This works at the start of the race and when changing labels. 118 | 119 | ### Lap notification 120 | 121 | /v1/camera/{id}/lap {lapnum} {laptime} {label} 122 | 123 | - Parameters 124 | - id ... Camera ID(1~4) 125 | - lapnum ... Lap number 126 | - laptime ... Lap time(seconds) 127 | - label ... Camera label 128 | - Example: Notify lap of camera 3(lap 5, 10.2 seconds) 129 | - /v1/camera/3/lap 5 10.2 "Whooper 3" 130 | 131 | ### Lap delete notification 132 | 133 | /v1/camera/{id}/lapdel {lapnum} 134 | 135 | - Parameters 136 | - id ... Camera ID(1~4) 137 | - lapnum ... Lap number 138 | - Example: Notify lap delete of camera 3(lap 5) 139 | - /v1/camera/3/lapdel 5 140 | 141 | ### Race result notification 142 | 143 | /v1/camera/{id}/result {label} {pos} {laps} {bestlap} {totaltime} 144 | 145 | - Parameters 146 | - id ... Camera ID(1~4) 147 | - label ... Camera label 148 | - pos ... Position 149 | - laps ... Laps 150 | - bestlap ... Best lap time(seconds) 151 | - totaltime ... Total time(minutes:seconds) 152 | - Example: Notify race result of camera 1(1st, 10 laps, 5.43 seconds, 62.13 seconds) 153 | - /v1/camera/1/lap "Whooper 1" 1 10 5.43 62.13 154 | 155 | This works at the end of the race. -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/MainGate_TypeA.pdf -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeA.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 25 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 61 | 69 | 75 | 87 | 99 | 111 | 123 | 135 | 147 | Tiny View PlusMain Gate Type A Rev.2for Middle SpeedOuter Circle : Φ700mmInner Circle : Φ400mmMarker : 120x120mm 194 | 204 | 208 | 215 | 222 | 229 | 235 | 242 | 249 | 256 | 263 | 270 | 277 | 284 | 291 | 292 | 293 | 304 | 315 | 326 | 337 | 348 | 359 | 370 | 381 | 392 | 393 | 398 | 474 | 475 | -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeA_A4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/MainGate_TypeA_A4.pdf -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeA_A4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 61 | 66 | 71 | 83 | 95 | 107 | 119 | 131 | 143 | 153 | 157 | 164 | 171 | 178 | 184 | 191 | 198 | 205 | 212 | 219 | 226 | 233 | 240 | 241 | 242 | 243 | 249 | 255 | 266 | 273 | 284 | Tiny View Plus - Main - Type A Rev.2 295 | A4 x 10 sheets 306 | 307 | 308 | -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/MainGate_TypeB.pdf -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeB.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 25 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 61 | 73 | 85 | 97 | 109 | 121 | 133 | 141 | Tiny View PlusMain Gate Type Bfor Low SpeedOuter Circle : Φ700mmInner Circle : Φ450mmMarker : 90x90mm 193 | 201 | 212 | 215 | 222 | 229 | 236 | 242 | 249 | 256 | 263 | 270 | 277 | 284 | 291 | 298 | 299 | 300 | 310 | 321 | 332 | 343 | 354 | 365 | 376 | 387 | 398 | 409 | 420 | 431 | 442 | 453 | 464 | 475 | 476 | 481 | 483 | 484 | 551 | 552 | -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/MainGate_TypeC.pdf -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeC.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 58 | 70 | 82 | 94 | 106 | 118 | 130 | 138 | Tiny View PlusMain Gate Type Cfor High SpeedOuter Circle : Φ800mmInner Circle : Φ400mmMarker : 160x160mm 190 | 198 | 209 | 212 | 219 | 226 | 233 | 239 | 246 | 253 | 260 | 267 | 274 | 281 | 288 | 295 | 296 | 297 | 307 | 318 | 329 | 340 | 351 | 362 | 373 | 384 | 385 | 390 | 392 | 393 | 398 | 405 | 408 | 419 | 428 | 437 | 446 | 447 | A3 459 | 460 | 461 | -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeC_A3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/MainGate_TypeC_A3.pdf -------------------------------------------------------------------------------- /docs/gate/MainGate_TypeC_A3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 53 | 58 | 70 | 82 | 94 | 106 | 118 | 130 | 135 | 140 | 151 | 154 | 161 | 168 | 175 | 181 | 188 | 195 | 202 | 209 | 216 | 223 | 230 | 237 | 238 | 239 | 249 | 250 | 256 | 258 | 259 | 265 | 270 | 275 | 280 | 285 | 290 | 295 | 300 | 305 | 310 | 315 | 320 | 325 | 330 | 331 | Tiny View Plus - Main Gate Type C - for High SpeedOD: 800mm, ID: 400mm, Marker: 160x160mm 353 | 364 | 365 | 366 | -------------------------------------------------------------------------------- /docs/gate/bakcup/MainGate_TypeA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/bakcup/MainGate_TypeA.pdf -------------------------------------------------------------------------------- /docs/gate/bakcup/MainGate_TypeD.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/gate/bakcup/MainGate_TypeD.pdf -------------------------------------------------------------------------------- /docs/gate/bakcup/MainGate_TypeD.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 25 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 61 | 73 | 85 | 97 | 109 | 121 | 133 | 141 | Tiny View PlusMain Gate Type Dfor Low SpeedOuter Circle : Φ820mmInner Circle : Φ470mmMarker : 150x150mm 193 | 201 | 212 | 215 | 222 | 229 | 236 | 242 | 249 | 256 | 263 | 270 | 277 | 284 | 291 | 298 | 299 | 300 | 311 | 322 | 333 | 344 | 355 | 366 | 377 | 388 | 399 | 400 | 406 | 408 | 409 | 489 | 490 | -------------------------------------------------------------------------------- /docs/gate/bakcup/Marker_Main_0.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 53 | 56 | 63 | 70 | 77 | 83 | 90 | 97 | 104 | 111 | 118 | 125 | 132 | 139 | 140 | vvv INSIDE vvv 151 | 152 | -------------------------------------------------------------------------------- /docs/img/argate_multi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/argate_multi.png -------------------------------------------------------------------------------- /docs/img/argate_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/argate_single.png -------------------------------------------------------------------------------- /docs/img/button_fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/button_fullscreen.png -------------------------------------------------------------------------------- /docs/img/button_quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/button_quit.png -------------------------------------------------------------------------------- /docs/img/button_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/button_settings.png -------------------------------------------------------------------------------- /docs/img/button_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/button_window.png -------------------------------------------------------------------------------- /docs/img/install_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/install_mac.png -------------------------------------------------------------------------------- /docs/img/marker_00_main_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/marker_00_main_a.png -------------------------------------------------------------------------------- /docs/img/marker_01_main_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/marker_01_main_b.png -------------------------------------------------------------------------------- /docs/img/marker_02_main_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/marker_02_main_c.png -------------------------------------------------------------------------------- /docs/img/marker_03_main_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/marker_03_main_d.png -------------------------------------------------------------------------------- /docs/img/overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/overview.jpg -------------------------------------------------------------------------------- /docs/img/qr_betaflight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/qr_betaflight.png -------------------------------------------------------------------------------- /docs/img/qr_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t-asano/tinyviewplus/f319b57e612ff3a8b1c7bad7af325a4d1ebf9060/docs/img/qr_screen.png -------------------------------------------------------------------------------- /of.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.device.audio-input 8 | 9 | com.apple.security.device.bluetooth 10 | 11 | com.apple.security.device.camera 12 | 13 | com.apple.security.device.usb 14 | 15 | com.apple.security.files.user-selected.read-write 16 | 17 | com.apple.security.network.client 18 | 19 | com.apple.security.network.server 20 | 21 | com.apple.security.print 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main() { 6 | ofSetupOpenGL(1280, 720, OF_WINDOW); 7 | ofRunApp(new ofApp()); 8 | } 9 | -------------------------------------------------------------------------------- /src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ofMain.h" 5 | #include "ofxTrueTypeFontUC.h" 6 | #include "ofxOsc.h" 7 | #include "ofxAruco.h" 8 | #include "highlyreliablemarkers.h" 9 | #include "ofxZxing.h" 10 | #include "ofxJoystick.h" 11 | #include "ofxXmlSettings.h" 12 | 13 | /* ---------- definitions ---------- */ 14 | 15 | // system 16 | #define APP_VER "v0.9.33 beta6" 17 | #define DEBUG_ENABLED false 18 | #define HELP_LINES 35 // must be <= OVLTXT_LINES 19 | #define SCENE_INIT 0 20 | #define SCENE_CAMS 1 21 | #define SCENE_MAIN 2 22 | #ifdef TARGET_OSX 23 | #define TVP_KEY_ALT OF_KEY_COMMAND 24 | #define TVP_STR_ALT "command" 25 | #else /* TARGET_OSX */ 26 | #define TVP_KEY_ALT OF_KEY_ALT 27 | #define TVP_STR_ALT "Alt" 28 | #endif /* TARGET_WIN32 TARGET_LINUX */ 29 | #define DFLT_SYS_STAT false 30 | #define TVP_VAL_PLUS 1 31 | #define TVP_VAL_MINUS -1 32 | 33 | // settings 34 | #define SETTINGS_FILE "settings.xml" 35 | #define SNM_SYS_SPCLANG "system:speechJpn" 36 | #define SNM_SYS_STAT "system:sysStat" 37 | #define SNM_OSCMON_ENA "oscMonitor:enabled" 38 | #define SNM_OSCMON_HOST "oscMonitor:host" 39 | #define SNM_OSCMON_PORT "oscMonitor:port" 40 | #define SNM_VIEW_FLLSCR "view:fullscreen" 41 | #define SNM_VIEW_BGIMG "view:bgImage" 42 | #define SNM_VIEW_CAMTRM "view:camTrim" 43 | #define SNM_VIEW_CAMFRM "view:camFrame" 44 | #define SNM_VIEW_LAPHST "view:lapHistMode" 45 | #define SNM_RACE_ARMODE "race:arMode" 46 | #define SNM_RACE_DRSECS "race:duraSecs" 47 | #define SNM_RACE_DRLAPS "race:duraLaps" 48 | #define SNM_RACE_MINLAP "race:minLapTime" 49 | #define SNM_RACE_STAGGR "race:staggStart" 50 | #define SNM_RACE_LAPTMO "race:lapAfterTmo" 51 | #define BTTN_FSCR_FILE "system/button_fullscreen.png" 52 | #define BTTN_QUIT_FILE "system/button_quit.png" 53 | #define BTTN_SETT_FILE "system/button_settings.png" 54 | #define BTTN_WNDW_FILE "system/button_window.png" 55 | 56 | // pilots 57 | #define PILOTS_FILE "pilots/pilots.xml" 58 | #define PLT_PILOT_LABEL "pilot:label_" 59 | 60 | // camera profile 61 | #define CAM_FPV_FILE "camera/fpv.xml" 62 | #define CFNM_NAME "camera:name" 63 | #define CFNM_GRAB_W "camera:grab:width" 64 | #define CFNM_GRAB_H "camera:grab:height" 65 | #define CFNM_CROP_X "camera:crop:x" 66 | #define CFNM_CROP_Y "camera:crop:y" 67 | #define CFNM_CROP_W "camera:crop:width" 68 | #define CFNM_CROP_H "camera:crop:height" 69 | #define CFNM_DRAW_ASPR "camera:draw:aspectRatio" 70 | 71 | // color 72 | #define COLOR_YELLOW 255,215,0 73 | #define COLOR_WHITE 255,255,255 74 | #define COLOR_LGRAY 127,127,127 75 | #define COLOR_DGRAY 15 76 | #define COLOR_BG_DARK 0,0,0,223 77 | #define COLOR_BG_MIDDLE 0,0,0,127 78 | #define COLOR_BG_LIGHT 0,0,0,31 79 | #define COLOR_ALERT 255,0,0 80 | // view 81 | #define FRAME_RATE 60 82 | #define MOVE_STEPS 10 83 | #define VERTICAL_SYNC true 84 | #define LOGO_LARGE_FILE "system/logo_large.png" 85 | #define LOGO_SMALL_FILE "system/logo_small.png" 86 | #define DFLT_WALL_FILE "system/background.png" 87 | #define DFLT_ICON_FILE "system/pilot_icon.png" 88 | #define CAMERA_MAXNUM 4 89 | #define CAMERA_WIDTH 640 90 | #define CAMERA_HEIGHT 480 91 | #define CAMERA_RATIO 1.3333 92 | #define FONT_P_FILE "system/GenShinGothic-P-Bold.ttf" 93 | #define FONT_M_FILE "system/GenShinGothic-Monospace-Bold.ttf" 94 | #define ICON_DIR "pilots/" 95 | #define ICON_WIDTH 50 96 | #define ICON_HEIGHT 50 97 | #define ICON_MARGIN_X 20 98 | #define ICON_MARGIN_Y 0 99 | #define NUMBER_HEIGHT 20 100 | #define NUMBER_MARGIN_X 1 101 | #define NUMBER_MARGIN_Y 35 102 | #define LABEL_HEIGHT 30 103 | #define LABEL_MARGIN_X 75 104 | #define LABEL_MARGIN_Y 40 105 | #define BASE_MARGIN_X 0 106 | #define BASE_MARGIN_Y 0 107 | #define BASE_WIDTH 20 108 | #define BASE_HEIGHT 50 109 | #define BASE_1_COLOR 201,58,64 110 | #define BASE_2_COLOR 160,194,56 111 | #define BASE_3_COLOR 0,116,191 112 | #define BASE_4_COLOR 248,128,23 113 | #define LAP_HEIGHT 20 114 | #define LAP_MARGIN_X 20 115 | #define LAP_MARGIN_Y 80 116 | #define LAPHIST_MD_OFF 0 117 | #define LAPHIST_MD_IN 1 118 | #define LAPHIST_MD_OUT 2 119 | #define LAPHIST_HEIGHT 15 120 | #define LAPHIST_MARGIN 8 121 | #define FRAME_LINEWIDTH 8 122 | #define DFLT_FSCR_ENBLD false 123 | #define DFLT_CAM_TRIM false 124 | #define DFLT_CAM_LAPHST LAPHIST_MD_OFF 125 | #define DFLT_CAM_FRAMED false 126 | #define ALIGN_LEFT 0 127 | #define ALIGN_CENTER 1 128 | #define ALIGN_RIGHT 2 129 | #define HIDECUR_TIME FRAME_RATE 130 | // overlay 131 | #define OVLMODE_NONE 0 132 | #define OVLMODE_HELP 1 133 | #define OVLMODE_MSG 2 134 | #define OVLMODE_RCRSLT 3 135 | #define OVLTXT_BLKS 13 136 | #define OVLTXT_LINES 35 137 | #define OVLTXT_LAPS 25 138 | #define OVLTXT_MARG 10 139 | #define OLVMSG_TIME FRAME_RATE 140 | #define INFO_HEIGHT 10 141 | #define WATCH_HEIGHT 40 142 | #define WATCH_OFFSET_Y 10 143 | // sound 144 | #define SND_BEEP_FILE "system/beep.wav" 145 | #define SND_BEEP3_FILE "system/beep3.wav" 146 | #define SND_COUNT_FILE "system/count.wav" 147 | #define SND_FINISH_FILE "system/finish.wav" 148 | #define SND_NOTIFY_FILE "system/notify.wav" 149 | #define SND_CANCEL_FILE "system/cancel.wav" 150 | // AR lap timer 151 | #define ARAP_MODE_NORM 0 152 | #define ARAP_MODE_LOOSE 1 153 | #define ARAP_MODE_OFF 2 154 | #define DFLT_ARAP_MODE ARAP_MODE_NORM 155 | #define DFLT_ARAP_RLAPS 10 156 | #define DFLT_ARAP_RSECS 0 157 | #define DFLT_ARAP_MNLAP 3 158 | #define DFLT_ARAP_SGATE false 159 | #define DFLT_ARAP_LAPTO false 160 | #define ARAP_MKR_FILE "system/marker.xml" 161 | #define ARAP_RESULT_DIR "results/" 162 | #define ARAP_MNUM_THR 2 163 | #define ARAP_MAX_RLAPS 10000 164 | #define ARAP_MAX_MNLAP 100 165 | #define ARAP_MAX_RSECS 36000 166 | #define ARAP_RSLT_SCRN 0 167 | #define ARAP_RSLT_FILE 1 168 | #define ARAP_RSLT_DELAY (FRAME_RATE * 3) 169 | #define ARAP_RECT_LINEW 5 170 | #define WATCH_COUNT_SEC 5 171 | // osc 172 | #define OSC_LISTEN_PORT 4000 173 | #define DFLT_OSCM_ENBLD true 174 | #define DFLT_OSCM_HOST "127.0.0.1" 175 | #define DFLT_OSCM_PORT 4001 176 | // speech 177 | #define DFLT_SPCH_ENBLD false 178 | #define SPCH_SLOT_NUM 8 179 | // QR code reader 180 | #define QR_CYCLE 6 181 | // gamepad 182 | #define GPAD_MAX_DEVS 4 183 | #define GPAD_ALT_BTN 4 184 | 185 | /* ---------- classes ---------- */ 186 | 187 | class tvpCamView { 188 | public: 189 | // camera 190 | bool visible; 191 | int moveSteps; 192 | int width; 193 | int height; 194 | int heightWide; 195 | int widthTarget; 196 | int heightTarget; 197 | int heightWideTarget; 198 | int posX; 199 | int posY; 200 | int posYWide; 201 | int posXTarget; 202 | int posYTarget; 203 | int posYWideTarget; 204 | float imageScale; 205 | bool needCrop; 206 | bool needResize; 207 | bool isWide; 208 | ofPixels resizedPixels; 209 | ofImage resizedImage; 210 | // base 211 | ofColor baseColor; 212 | int basePosX; 213 | int basePosY; 214 | int basePosXTarget; 215 | int basePosYTarget; 216 | int baseWidth; 217 | int baseHeight; 218 | // number 219 | int numberPosX; 220 | int numberPosY; 221 | int numberPosXTarget; 222 | int numberPosYTarget; 223 | // icon 224 | ofImage iconImage; 225 | int iconPosX; 226 | int iconPosY; 227 | int iconPosXTarget; 228 | int iconPosYTarget; 229 | // label 230 | string labelString; 231 | int labelPosX; 232 | int labelPosY; 233 | int labelPosXTarget; 234 | int labelPosYTarget; 235 | // lap 236 | int lapPosX; 237 | int lapPosY; 238 | int lapPosXTarget; 239 | int lapPosYTarget; 240 | float lastLapTime; 241 | // AR lap timer 242 | ofxAruco aruco; 243 | int foundMarkerNum; 244 | int foundValidMarkerNum; 245 | bool enoughMarkers; 246 | float prevElapsedSec; 247 | int totalLaps; 248 | string lapHistName[ARAP_MAX_RLAPS + 1]; 249 | float lapHistLapTime[ARAP_MAX_RLAPS + 1]; 250 | float lapHistElpTime[ARAP_MAX_RLAPS + 1]; 251 | int flickerCount; 252 | int flickerValidCount; 253 | int racePosition; 254 | // QR reader 255 | bool qrScanned; 256 | }; 257 | 258 | 259 | class tvpCamProf { 260 | public: 261 | bool enabled; 262 | string name; 263 | int grabW; 264 | int grabH; 265 | int cropX; 266 | int cropY; 267 | int cropW; 268 | int cropH; 269 | string drawAspr; 270 | bool needCrop; 271 | bool needResize; 272 | bool isWide; 273 | }; 274 | 275 | class ofApp : public ofBaseApp { 276 | public: 277 | void setup(); 278 | void update(); 279 | void draw(); 280 | void keyPressed(int key); 281 | void keyReleased(int key); 282 | void mouseMoved(int x, int y); 283 | void mouseDragged(int x, int y, int button); 284 | void mousePressed(int x, int y, int button); 285 | void mouseReleased(int x, int y, int button); 286 | void mouseEntered(int x, int y); 287 | void mouseExited(int x, int y); 288 | void windowResized(int w, int h); 289 | void dragEvent(ofDragInfo dragInfo); 290 | void gotMessage(ofMessage msg); 291 | void exit(); 292 | }; 293 | 294 | /* ---------- functions ---------- */ 295 | 296 | // -- splash -- 297 | void setupInit(); 298 | void loadWallImage(string); 299 | void loadSettingsFile(); 300 | void saveSettingsFile(); 301 | void savePilotsFile(); 302 | void loadPilotsFile(); 303 | void loadCameraProfileFile(); 304 | void setupOsc(); 305 | void updateInit(); 306 | void drawInit(); 307 | // -- camera setup -- 308 | void setupCamCheck(); 309 | void updateCamCheck(); 310 | void drawCamCheck(); 311 | void keyPressedCamCheck(int); 312 | void reloadCameras(); 313 | // -- main -- 314 | // common 315 | void initConfig(); 316 | string getUserLocaleName(); 317 | void toggleSysStat(); 318 | // view 319 | void grabberUpdateResize(int); 320 | void toggleCameraSolo(int); 321 | void enableCameraSolo(int); 322 | void resetCameraSolo(); 323 | void toggleCameraVisibility(int); 324 | int getCameraIdxNthVisibleAll(int); 325 | int getCameraIdxNthVisibleSub(int); 326 | void toggleFullscreen(); 327 | void toggleCameraTrim(); 328 | void toggleCameraFrame(); 329 | void setupColors(); 330 | void changeCameraLabel(int); 331 | void changeCameraIcon(int); 332 | void changeCameraIconPath(int, string, bool); 333 | void autoSelectCameraIcon(int, string); 334 | void changeWallImage(); 335 | void setWallParams(); 336 | void setViewParams(); 337 | int calcViewParam(int, int, int); 338 | void updateViewParams(); 339 | // osc 340 | void recvOsc(); 341 | void recvOscCameraString(int, string, string); 342 | void recvOscCameraFloat(int, string, float); 343 | void recvOscSpeech(string, string); 344 | void sendOscSystemInfo(string); 345 | void sendOscRaceEvent(string); 346 | void sendOscCameraLap(int, int, float, string); 347 | void sendOscCameraLapDelete(int, int); 348 | void sendOscCameraLabel(int, string); 349 | void sendOscCameraLabelAll(); 350 | void sendOscCameraResult(int, string, int, int, float, float); 351 | // speech 352 | void toggleSpeechLang(); 353 | void autoSelectSpeechLang(); 354 | void speakLap(int, float, int); 355 | void setNextNotifyRemainSecs(int); 356 | void speakRemainTime(int); 357 | void speakAny(string, string); 358 | // draw 359 | void drawCameraImage(int); 360 | void drawCameraFrame(int); 361 | void drawCameraARMarker(int, bool); 362 | void drawCameraPilot(int, bool); 363 | void drawCameraLapTime(int, bool); 364 | void drawCameraLapHistory(int, bool, bool); 365 | void drawCamera(int); 366 | string getWatchString(float); 367 | void drawWatch(); 368 | void drawInfo(); 369 | void drawStringWithShadow(ofxTrueTypeFontUC*, ofColor, ofColor, string, int, int); 370 | void drawSystemButtons(); 371 | // input 372 | void keyPressedOverlayHelp(int); 373 | void keyPressedOverlayHelp(int); 374 | void keyPressedOverlayResult(int); 375 | void keyPressedOverlayNone(int); 376 | void mouseReleasedOverlayNone(int, int, int); 377 | // race 378 | void toggleRace(); 379 | void initRaceVars(); 380 | void startRace(); 381 | void stopRace(bool); 382 | bool isVariousPilots(int); 383 | bool isVariousPilotsAll(); 384 | bool isRecordedLaps(); 385 | float getBestLap(int); 386 | int getMaxLaps(); 387 | string getLapStr(float); 388 | void pushLapRecord(int, float); 389 | void popLapRecord(int); 390 | void updateRacePositions(); 391 | void toggleARLap(); 392 | void changeMinLap(int); 393 | void changeRaceTime(int); 394 | void changeRaceLaps(int); 395 | void changeRaceTimeAndLaps(); 396 | void toggleUseStartGate(); 397 | void toggleLapAfterTimeout(); 398 | // overlay - common 399 | void setOverlayMode(int); 400 | void loadOverlayFont(); 401 | void drawStringBlock(ofxTrueTypeFontUC*, string, int , int, int, int, int); 402 | void drawLineBlock(int, int, int, int, int); 403 | void drawULineBlock(int, int, int, int, int); 404 | // overlay - race result 405 | void generateDummyData(); 406 | void fwriteRaceResult(); 407 | int getRaceResultPages(); 408 | void processRaceResultDisplay(); 409 | void drawRaceResult(int); 410 | // overlay - help 411 | void drawHelp(); 412 | void drawHelpBody(int); 413 | // overlay - message 414 | void initOverlayMessage(); 415 | void setOverlayMessage(string); 416 | void drawOverlayMessageCore(ofxTrueTypeFontUC*, string); 417 | void drawOverlayMessage(); 418 | // QR Code reader 419 | #ifdef TARGET_WIN32 420 | string utf8ToAnsi(string); 421 | string ansiToUtf8(string); 422 | #endif /* TARGET_WIN32 */ 423 | void toggleQrReader(); 424 | void processQrReader(); 425 | // gamepad 426 | void checkGamePad(float); 427 | // others 428 | void toggleLapHistory(); 429 | void activateCursor(); 430 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /test/osc_debug.js: -------------------------------------------------------------------------------- 1 | // OSC debugger 2 | 3 | var osc = require('node-osc'); 4 | var client = new osc.Client('127.0.0.1', 4000); 5 | 6 | function sendOsc(addr, arg1, wait) { 7 | var is_str = (typeof arg1 === 'string' || arg1 instanceof String); 8 | var ext = is_str ? '"' : ''; 9 | setTimeout(function () { 10 | console.log(addr + ' ' + ext + arg1 + ext); 11 | client.send(addr, arg1, function () {}); 12 | }, wait); 13 | } 14 | 15 | function exit() { 16 | client.kill(); 17 | process.exit; 18 | } 19 | 20 | function test() { 21 | var wait = 0; 22 | var step = 800; 23 | var step_lap = 3000; 24 | var step_spc = 1200; 25 | console.log('Sending OSC message to udp://127.0.0.1:4000'); 26 | // camera solo 27 | sendOsc("/v1/camera/1/solo", "on", wait += step); 28 | sendOsc("/v1/camera/1/solo", "off", wait += step); 29 | sendOsc("/v1/camera/2/solo", "on", wait += step); 30 | sendOsc("/v1/camera/2/solo", "off", wait += step); 31 | sendOsc("/v1/camera/3/solo", "on", wait += step); 32 | sendOsc("/v1/camera/3/solo", "off", wait += step); 33 | sendOsc("/v1/camera/4/solo", "on", wait += step); 34 | sendOsc("/v1/camera/4/solo", "off", wait += step); 35 | // camera display 36 | sendOsc("/v1/camera/1/display", "off", wait += step); 37 | sendOsc("/v1/camera/2/display", "off", wait += step); 38 | sendOsc("/v1/camera/3/display", "off", wait += step); 39 | sendOsc("/v1/camera/4/display", "off", wait += step); 40 | sendOsc("/v1/camera/1/display", "on", wait += step); 41 | sendOsc("/v1/camera/2/display", "on", wait += step); 42 | sendOsc("/v1/camera/3/display", "on", wait += step); 43 | sendOsc("/v1/camera/4/display", "on", wait += step); 44 | // camera label 45 | sendOsc("/v1/camera/1/label", "パイロット1", wait += step); 46 | sendOsc("/v1/camera/2/label", "パイロット2", wait += step); 47 | sendOsc("/v1/camera/3/label", "パイロット3", wait += step); 48 | sendOsc("/v1/camera/4/label", "パイロット4", wait += step); 49 | sendOsc("/v1/camera/1/label", "sample pilot", wait += step); 50 | sendOsc("/v1/camera/2/label", "sample pilot", wait += step); 51 | sendOsc("/v1/camera/3/label", "sample pilot", wait += step); 52 | sendOsc("/v1/camera/4/label", "sample pilot", wait += step); 53 | sendOsc("/v1/camera/1/label", "Pilot1", wait += step); 54 | sendOsc("/v1/camera/2/label", "Pilot2", wait += step); 55 | sendOsc("/v1/camera/3/label", "Pilot3", wait += step); 56 | sendOsc("/v1/camera/4/label", "Pilot4", wait += step); 57 | // camera lap 58 | sendOsc("/v1/camera/1/lap", "add", wait += step); 59 | sendOsc("/v1/camera/2/lap", "add", wait += step_lap); 60 | sendOsc("/v1/camera/3/lap", "add", wait += step_lap); 61 | sendOsc("/v1/camera/4/lap", "add", wait += step_lap); 62 | sendOsc("/v1/camera/1/lap", "del", wait += step_lap); 63 | sendOsc("/v1/camera/2/lap", "del", wait += step); 64 | sendOsc("/v1/camera/3/lap", "del", wait += step); 65 | sendOsc("/v1/camera/4/lap", "del", wait += step); 66 | // camera laptime 67 | sendOsc("/v1/camera/1/laptime", 62.09, wait += step); 68 | sendOsc("/v1/camera/2/laptime", 56.20, wait += step_lap); 69 | sendOsc("/v1/camera/3/laptime", 58.83, wait += step_lap); 70 | sendOsc("/v1/camera/4/laptime", 45.31, wait += step_lap); 71 | sendOsc("/v1/camera/1/laptime", 0, wait += step_lap); 72 | sendOsc("/v1/camera/2/laptime", 0, wait += step); 73 | sendOsc("/v1/camera/3/laptime", 0, wait += step); 74 | sendOsc("/v1/camera/4/laptime", 0, wait += step); 75 | // speech 76 | sendOsc("/v1/speech/jp/say", "ドローンで遊ぼう", wait += step); 77 | sendOsc("/v1/speech/en/say", "You can fly!", wait += step_spc); 78 | // exit 79 | setTimeout(exit, wait += step); 80 | } 81 | 82 | test(); 83 | -------------------------------------------------------------------------------- /test/osc_debug_lap.js: -------------------------------------------------------------------------------- 1 | // OSC debugger 2 | 3 | var osc = require('node-osc'); 4 | var client = new osc.Client('127.0.0.1', 4000); 5 | 6 | function sendOsc(addr, arg1, wait) { 7 | var is_str = (typeof arg1 === 'string' || arg1 instanceof String); 8 | var ext = is_str ? '"' : ''; 9 | setTimeout(function () { 10 | console.log(addr + ' ' + ext + arg1 + ext); 11 | client.send(addr, arg1, function () {}); 12 | }, wait); 13 | } 14 | 15 | function exit() { 16 | client.kill(); 17 | process.exit; 18 | } 19 | 20 | function test() { 21 | var wait = 0; 22 | var step = 800; 23 | var step_lap = 2000; 24 | var step_spc = 1000; 25 | console.log('Sending OSC message to udp://127.0.0.1:4000'); 26 | // camera lap 27 | sendOsc("/v1/camera/1/lap", "add", wait += step); 28 | sendOsc("/v1/camera/2/lap", "add", wait += step_lap); 29 | sendOsc("/v1/camera/3/lap", "add", wait += step_lap); 30 | sendOsc("/v1/camera/4/lap", "add", wait += step_lap); 31 | sendOsc("/v1/camera/1/lap", "del", wait += step_lap); 32 | sendOsc("/v1/camera/2/lap", "del", wait += step); 33 | sendOsc("/v1/camera/3/lap", "del", wait += step); 34 | sendOsc("/v1/camera/4/lap", "del", wait += step); 35 | // exit 36 | setTimeout(exit, wait += step); 37 | } 38 | 39 | test(); 40 | -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "osc_debug.js", 6 | "dependencies": { 7 | "node-osc": "^2.1.0" 8 | }, 9 | "devDependencies": {}, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "", 14 | "license": "ISC" 15 | } 16 | --------------------------------------------------------------------------------