adding new files

This commit is contained in:
countcobolt 2023-07-11 17:40:36 +02:00
parent c288469673
commit 0caec43b06
96 changed files with 5057975 additions and 0 deletions

BIN
Jan_zwembad_bakje-Body.stl Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

137
Pedals/PedalJoy2021.ino Normal file
View file

@ -0,0 +1,137 @@
#undef DEBUG
#define NUM_BUTTONS 40 // you don't need to change this value
#define NUM_AXES 8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO, don't need to change this value.
typedef struct joyReport_t {
int16_t axis[NUM_AXES];
uint8_t button[(NUM_BUTTONS + 7) / 8]; // 8 buttons per byte
} joyReport_t;
joyReport_t joyReport;
uint8_t btn[12];
int fulloff = 0;
void setup(void);
void loop(void);
void setButton(joyReport_t *joy, uint8_t button);
void clearButton(joyReport_t *joy, uint8_t button);
void sendJoyReport(joyReport_t *report);
void setup()
{
//set pin to input Button
for ( int portId = 02; portId < 13; portId ++ )
{
pinMode( portId, INPUT_PULLUP);
}
Serial.begin(115200);
delay(200);
for (uint8_t ind = 0; ind < 8; ind++) {
joyReport.axis[ind] = ind * 1000;
}
for (uint8_t ind = 0; ind < sizeof(joyReport.button); ind++) {
joyReport.button[ind] = 0;
}
}
// Send an HID report to the USB interface
void sendJoyReport(struct joyReport_t *report)
{
#ifndef DEBUG
Serial.write((uint8_t *)report, sizeof(joyReport_t));
#else
// dump human readable output for debugging
for (uint8_t ind = 0; ind < NUM_AXES; ind++) {
Serial.print("axis[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->axis[ind]);
Serial.print(" ");
}
Serial.println();
for (uint8_t ind = 0; ind < NUM_BUTTONS / 8; ind++) {
Serial.print("button[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->button[ind], HEX);
Serial.print(" ");
}
Serial.println();
#endif
}
// turn a button on
void setButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] |= 1 << bit;
}
// turn a button off
void clearButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] &= ~(1 << bit);
}
/*
Read Digital port for Button
Read Analog port for axis
*/
void loop()
{
for (int bt = 1; bt < 13; bt ++)
{
// btn[bt] = digitalRead(bt + 1);
btn[bt] = LOW;
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == LOW)
{
setButton(&joyReport, on + 16);
delay(1);
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == HIGH)
{
clearButton(&joyReport, on + 16);
}
}
}
//for (uint8_t axis = 0; axis < 1; axis++) {
// joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768, 32767 );
//}
joyReport.axis[0] = 0;
joyReport.axis[1] = 0;
joyReport.axis[2] = map(analogRead(2), 0, 1023, -32768, 32767 );
joyReport.axis[3] = map(analogRead(3), 0, 1023, -32768, 32767 );
joyReport.axis[4] = map(analogRead(4), 0, 1023, -32768, 32767 );
joyReport.axis[5] = 0;
joyReport.axis[6] = 0;
joyReport.axis[7] = 0;
joyReport.axis[8] = 0;
//Send Data to HID
sendJoyReport(&joyReport);
delay(35);
fulloff = 0;
}

137
Pedals/PedalJoy2021.txt Normal file
View file

@ -0,0 +1,137 @@
#undef DEBUG
#define NUM_BUTTONS 40 // you don't need to change this value
#define NUM_AXES 8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO, don't need to change this value.
typedef struct joyReport_t {
int16_t axis[NUM_AXES];
uint8_t button[(NUM_BUTTONS + 7) / 8]; // 8 buttons per byte
} joyReport_t;
joyReport_t joyReport;
uint8_t btn[12];
int fulloff = 0;
void setup(void);
void loop(void);
void setButton(joyReport_t *joy, uint8_t button);
void clearButton(joyReport_t *joy, uint8_t button);
void sendJoyReport(joyReport_t *report);
void setup()
{
//set pin to input Button
for ( int portId = 02; portId < 13; portId ++ )
{
pinMode( portId, INPUT_PULLUP);
}
Serial.begin(115200);
delay(200);
for (uint8_t ind = 0; ind < 8; ind++) {
joyReport.axis[ind] = ind * 1000;
}
for (uint8_t ind = 0; ind < sizeof(joyReport.button); ind++) {
joyReport.button[ind] = 0;
}
}
// Send an HID report to the USB interface
void sendJoyReport(struct joyReport_t *report)
{
#ifndef DEBUG
Serial.write((uint8_t *)report, sizeof(joyReport_t));
#else
// dump human readable output for debugging
for (uint8_t ind = 0; ind < NUM_AXES; ind++) {
Serial.print("axis[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->axis[ind]);
Serial.print(" ");
}
Serial.println();
for (uint8_t ind = 0; ind < NUM_BUTTONS / 8; ind++) {
Serial.print("button[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->button[ind], HEX);
Serial.print(" ");
}
Serial.println();
#endif
}
// turn a button on
void setButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] |= 1 << bit;
}
// turn a button off
void clearButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] &= ~(1 << bit);
}
/*
Read Digital port for Button
Read Analog port for axis
*/
void loop()
{
for (int bt = 1; bt < 13; bt ++)
{
// btn[bt] = digitalRead(bt + 1);
btn[bt] = LOW;
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == LOW)
{
setButton(&joyReport, on + 16);
delay(1);
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == HIGH)
{
clearButton(&joyReport, on + 16);
}
}
}
//for (uint8_t axis = 0; axis < 1; axis++) {
// joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768, 32767 );
//}
joyReport.axis[0] = 0;
joyReport.axis[1] = 0;
joyReport.axis[2] = map(analogRead(2), 0, 1023, -32768, 32767 );
joyReport.axis[3] = map(analogRead(3), 0, 1023, -32768, 32767 );
joyReport.axis[4] = map(analogRead(4), 0, 1023, -32768, 32767 );
joyReport.axis[5] = 0;
joyReport.axis[6] = 0;
joyReport.axis[7] = 0;
joyReport.axis[8] = 0;
//Send Data to HID
sendJoyReport(&joyReport);
delay(35);
fulloff = 0;
}

339
Pedals/esptool/LICENSE Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

21
Pedals/esptool/README.md Normal file
View file

@ -0,0 +1,21 @@
# esptool.py
A Python-based, open-source, platform-independent utility to communicate with the ROM bootloader in Espressif chips.
[![Test esptool](https://github.com/espressif/esptool/actions/workflows/test_esptool.yml/badge.svg?branch=master)](https://github.com/espressif/esptool/actions/workflows/test_esptool.yml) [![Build esptool](https://github.com/espressif/esptool/actions/workflows/build_esptool.yml/badge.svg?branch=master)](https://github.com/espressif/esptool/actions/workflows/build_esptool.yml)
## Documentation
Visit the [documentation](https://docs.espressif.com/projects/esptool/) or run `esptool.py -h`.
## Contribute
If you're interested in contributing to esptool.py, please check the [contributions guide](https://docs.espressif.com/projects/esptool/en/latest/contributing.html).
## About
esptool.py was initially created by Fredrik Ahlberg (@[themadinventor](https://github.com/themadinventor/)), and later maintained by Angus Gratton (@[projectgus](https://github.com/projectgus/)). It is now supported by Espressif Systems. It has also received improvements from many members of the community.
## License
This document and the attached source code are released as Free Software under GNU General Public License Version 2 or later. See the accompanying [LICENSE file](https://github.com/espressif/esptool/blob/master/LICENSE) for a copy.

Binary file not shown.

BIN
Pedals/esptool/espefuse Normal file

Binary file not shown.

BIN
Pedals/esptool/espsecure Normal file

Binary file not shown.

BIN
Pedals/esptool/esptool Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Pedals/files/Limiter.stl Normal file

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,137 @@
#undef DEBUG
#define NUM_BUTTONS 40 // you don't need to change this value
#define NUM_AXES 8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO, don't need to change this value.
typedef struct joyReport_t {
int16_t axis[NUM_AXES];
uint8_t button[(NUM_BUTTONS + 7) / 8]; // 8 buttons per byte
} joyReport_t;
joyReport_t joyReport;
uint8_t btn[12];
int fulloff = 0;
void setup(void);
void loop(void);
void setButton(joyReport_t *joy, uint8_t button);
void clearButton(joyReport_t *joy, uint8_t button);
void sendJoyReport(joyReport_t *report);
void setup()
{
//set pin to input Button
for ( int portId = 02; portId < 13; portId ++ )
{
pinMode( portId, INPUT_PULLUP);
}
Serial.begin(115200);
delay(200);
for (uint8_t ind = 0; ind < 8; ind++) {
joyReport.axis[ind] = ind * 1000;
}
for (uint8_t ind = 0; ind < sizeof(joyReport.button); ind++) {
joyReport.button[ind] = 0;
}
}
// Send an HID report to the USB interface
void sendJoyReport(struct joyReport_t *report)
{
#ifndef DEBUG
Serial.write((uint8_t *)report, sizeof(joyReport_t));
#else
// dump human readable output for debugging
for (uint8_t ind = 0; ind < NUM_AXES; ind++) {
Serial.print("axis[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->axis[ind]);
Serial.print(" ");
}
Serial.println();
for (uint8_t ind = 0; ind < NUM_BUTTONS / 8; ind++) {
Serial.print("button[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->button[ind], HEX);
Serial.print(" ");
}
Serial.println();
#endif
}
// turn a button on
void setButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] |= 1 << bit;
}
// turn a button off
void clearButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] &= ~(1 << bit);
}
/*
Read Digital port for Button
Read Analog port for axis
*/
void loop()
{
for (int bt = 1; bt < 13; bt ++)
{
// btn[bt] = digitalRead(bt + 1);
btn[bt] = LOW;
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == LOW)
{
setButton(&joyReport, on + 16);
delay(1);
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == HIGH)
{
clearButton(&joyReport, on + 16);
}
}
}
//for (uint8_t axis = 0; axis < 1; axis++) {
// joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768, 32767 );
//}
joyReport.axis[0] = 0;
joyReport.axis[1] = 0;
joyReport.axis[2] = map(analogRead(2), 0, 1023, -32768, 32767 );
joyReport.axis[3] = map(analogRead(3), 0, 1023, -32768, 32767 );
joyReport.axis[4] = map(analogRead(4), 0, 1023, -32768, 32767 );
joyReport.axis[5] = 0;
joyReport.axis[6] = 0;
joyReport.axis[7] = 0;
joyReport.axis[8] = 0;
//Send Data to HID
sendJoyReport(&joyReport);
delay(35);
fulloff = 0;
}

View file

@ -0,0 +1,137 @@
#undef DEBUG
#define NUM_BUTTONS 40 // you don't need to change this value
#define NUM_AXES 8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO, don't need to change this value.
typedef struct joyReport_t {
int16_t axis[NUM_AXES];
uint8_t button[(NUM_BUTTONS + 7) / 8]; // 8 buttons per byte
} joyReport_t;
joyReport_t joyReport;
uint8_t btn[12];
int fulloff = 0;
void setup(void);
void loop(void);
void setButton(joyReport_t *joy, uint8_t button);
void clearButton(joyReport_t *joy, uint8_t button);
void sendJoyReport(joyReport_t *report);
void setup()
{
//set pin to input Button
for ( int portId = 02; portId < 13; portId ++ )
{
pinMode( portId, INPUT_PULLUP);
}
Serial.begin(115200);
delay(200);
for (uint8_t ind = 0; ind < 8; ind++) {
joyReport.axis[ind] = ind * 1000;
}
for (uint8_t ind = 0; ind < sizeof(joyReport.button); ind++) {
joyReport.button[ind] = 0;
}
}
// Send an HID report to the USB interface
void sendJoyReport(struct joyReport_t *report)
{
#ifndef DEBUG
Serial.write((uint8_t *)report, sizeof(joyReport_t));
#else
// dump human readable output for debugging
for (uint8_t ind = 0; ind < NUM_AXES; ind++) {
Serial.print("axis[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->axis[ind]);
Serial.print(" ");
}
Serial.println();
for (uint8_t ind = 0; ind < NUM_BUTTONS / 8; ind++) {
Serial.print("button[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->button[ind], HEX);
Serial.print(" ");
}
Serial.println();
#endif
}
// turn a button on
void setButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] |= 1 << bit;
}
// turn a button off
void clearButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;
joy->button[index] &= ~(1 << bit);
}
/*
Read Digital port for Button
Read Analog port for axis
*/
void loop()
{
for (int bt = 1; bt < 13; bt ++)
{
// btn[bt] = digitalRead(bt + 1);
btn[bt] = LOW;
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == LOW)
{
setButton(&joyReport, on + 16);
delay(1);
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == HIGH)
{
clearButton(&joyReport, on + 16);
}
}
}
//for (uint8_t axis = 0; axis < 1; axis++) {
// joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768, 32767 );
//}
joyReport.axis[0] = 0;
joyReport.axis[1] = 0;
joyReport.axis[2] = map(analogRead(2), 0, 1023, -32768, 32767 );
joyReport.axis[3] = map(analogRead(3), 0, 1023, -32768, 32767 );
joyReport.axis[4] = map(analogRead(4), 0, 1023, -32768, 32767 );
joyReport.axis[5] = 0;
joyReport.axis[6] = 0;
joyReport.axis[7] = 0;
joyReport.axis[8] = 0;
//Send Data to HID
sendJoyReport(&joyReport);
delay(35);
fulloff = 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Pedals/files/Pedal_Heel.stl Normal file

Binary file not shown.

BIN
Pedals/files/Pedal_Hole.stl Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Pedals/files/Yaw_Gear.stl Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
Pedals/images/Limiter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

BIN
Pedals/images/Yaw_Gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
chair_stop-Body.stl Normal file

Binary file not shown.

BIN
chair_stop.FCStd Normal file

Binary file not shown.

BIN
chair_stop.FCStd1 Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

23392
motion_sim/Flyer/BK12.STEP Normal file

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,768 @@
<!doctype html>
<!-- to be used with visual studio extension 'markup editor' for auto html generation -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
<style>
html {
font-size: 18px;
max-width: 100%;
}
body {
box-sizing: border-box;
min-width: 200px;
max-width: 1200px;
margin: 0 auto;
color: #444;
font-family: "Segoe UI",Helvetica,Arial,sans-serif;
font-weight: 300;
line-height: 1.45;
padding: .25rem;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: Helvetica, sans-serif;
}
h1,
h2 {
border-bottom: 2px solid #fafafa;
margin-bottom: 1.15rem;
padding-bottom: .5rem;
text-align: center;
border-bottom: 1px solid #21262d;
}
</style>
<title>OpenXR Motion Compensation</title>
</head>
<body>
<content><h1 id="openxr-motion-compensation">OpenXR Motion Compensation</h1>
<p><strong>DISCLAIMER: This software is distributed as-is, without any warranties or conditions of any kind. Use at your own risks!</strong></p>
<p>Version: 0.2.6</p>
<p><strong>This document contains instructions on how to use OpenXR motion compensation <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#api-layers">API layer</a>.</strong></p>
<h2 id="purpose-of-openxr-motion-compensation">Purpose of OpenXR Motion Compensation</h2>
<p>When using a motion rig in combination with a VR headset (hmd) he movement of the rig causes the in-game camera to change along with your position in the real world. In simulations for example you're basically feel being pushed around inside the cockpit when the motion rig moves.<br />
Motion compensation reduces or ideally removes that effect by locking the in-game world to the pose of the motion rig.
This software aims to provide an API layer for motion compensation to be used with applications and hmds supporting the OpenXR standard.<br />
To be able to do that, the software needs to be informed on the motion rig movement / position. This can be achieved using a tracker, which is either a physical object attached to the motion rig and tracked by the VR runtime (e.g. a motion controller or a vive puck) or a virtual tracker using data from the motion software driving the motion rig.</p>
<p>Limitations:</p>
<ul>
<li>The motion compensation API Layer is made for Windows 64-bit only.</li>
<li>The software (obviously) only works with VR/AR applications using an OpenXR runtime implementation.</li>
</ul>
<h2 id="contact">Contact</h2>
<p>Feel free to join our <a href="https://discord.gg/BVWugph5XF">Discord community</a> or to send an e-mail to <a href="mailto:oxrmc@mailbox.org"><strong>oxrmc@mailbox.org</strong></a> for feedback and assistance.</p>
<p>You can find the <a href="https://github.com/BuzzteeBear/OpenXR-MotionCompensation">source code</a> and the <a href="https://github.com/BuzzteeBear/OpenXR-MotionCompensation/releases">latest release</a> or report issues on github.</p>
<p>If you are (or know someone) willing and able to support the software development (mostly C++, maybe some GUI stuff later on) side of the project, feel free to contact <strong>@BuzzteeBear</strong> on the Discord server to ask about ways to contribute.</p>
<p>Donations to the project are very welcome and can be made via <a href="https://www.paypal.com/donate/?hosted_button_id=Q64DT2ADFCBU8">Paypal</a>.<br />
On explicit user request you can also sponsor the project via <a href="https://github.com/sponsors/BuzzteeBear?o=esb">GitHub Sponsors</a></p>
<h2 id="installation">Installation</h2>
<h3 id="run-installer-executable">Run installer executable</h3>
<p>Just double click the installation executable called <code>Install_OpenXR-MotionCompensation_&lt;current_version&gt;.exe</code> and follow the instructions.
A few hints regarding the installation process:</p>
<ul>
<li>If you're upgrading from a version prior to 0.2.0, it is recommended to target the installation directory already existing. This will allow the installer to transfer your existing configuration files into the <code>appdata/local/OpenXR-MotionCompensation</code> directory that is used from version 0.2.0 onwards.</li>
<li>Using a subdirectory of <code>program files</code> as installation target is recommended, especially for compatibility with WMR based headsets.</li>
<li>Although the installation needs adminstrative privileges make sure to run the installation executable using the windows account you're using to launch your games/Open XR applications. This enables the installer to put the configuraton file(s) into the correct appdata directory.</li>
<li>If somethimng goes wrong on installation and you don't know what or why, you can check the log file <code>Setup Log &lt;yyyy-mm-dd xxx&gt;.txt</code> that is created in the <code>%TEMP%</code> folder.</li>
</ul>
<h3 id="conflict-with-other-openxr-api-layers">Conflict with other OpenXR API layers</h3>
<p>There may be issues with other OpenXR API layers that are installed on your system. For the most part they can be solved by using the correct order of installation (because that implicitly determines the order in which the layers are loaded).<br />
According to user feedback following constraints seem to be working:</p>
<ul>
<li><strong>XRNeckSaver</strong> needs to be installed before OXRMC.</li>
<li><strong>OpenKneeBoard</strong> needs to be installed before OXRMC.
<ul>
<li>but it is (or at least was at some point) putting its registry key in <code>...HKEY_CURRENT_USER/...</code> while OXRMC uses <code>...HKEY_LOCAL_MACHINE/...</code> . So if you're having trouble changing the loading order, try moving the key for OpenKneeboard from <code>Computer\HKEY_CURRENT_USER\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Implicit</code> to <code>Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Implicit</code>.</li>
</ul>
</li>
<li>if you install one of the above with after OXRMC, you can just run the OXRMC installer afterwards to modify loading order.</li>
</ul>
<h3 id="optional-confirm-correct-installation">Optional: Confirm correct installation</h3>
<p>You can use the application <a href="https://github.com/maluoi/openxr-explorer/releases">OpenXR Explorer</a> to verify the correct installation:</p>
<ul>
<li>Install OpenXR Explorer</li>
<li>Connect your headset</li>
<li>Start your corresponding VR runtime application (e.g. SteamVR, Oculus App, Mixed Reality Portal, Varjo Base, PiTool, etc.)</li>
<li>Start OpenXR explorer</li>
<li>Search for the section <code>xrEnumerateApiLayerProperties</code> (should be in the middle column at the bottom by default)</li>
<li>Check if the entry <code>XR_APILAYER_NOVENDOR_motion_compensation</code> with version <code>v1</code> exists</li>
</ul>
<h3 id="update">Update</h3>
<p>To get OXRMC udpated, download and run the latest installation executable from <a href="https://github.com/BuzzteeBear/OpenXR-MotionCompensation/releases">Github</a>. If you want to change the installation directory you have to uninstall the previous version first.</p>
<h3 id="uninstallation">Uninstallation</h3>
<p>To remove the OpenXR-MotionCompensation layer just use windows settings/control panel as you would do witgh any other application. During uninstallation you can choose to delete your configuration and log files in the appdata directory or to keep them for later use.</p>
<ul>
<li>If somethimng goes wrong on installation and you don't know what or why, you can check the log file <code>Uninstall Log &lt;yyyy-mm-dd xxx&gt;.txt</code> that is created in the <code>%TEMP%</code> folder.</li>
</ul>
<h2 id="configuration">Configuration</h2>
<p>Configuration files can be found at <code>...\Users\*&lt;Your_Username&gt;*\AppData\Local\OpenXR-MotionCompensation\OpenXR-MotionCompensation.log</code>.
After intial installtion this directory contains the default configuration file <code>OpenXR-MotionCompensation.ini</code>. You can make changes to that file to configure options you want to be the same for all OpenXR applications.
Upon starting an OpenXR application with the API layer active for the first time, a configuration file named after the application is created in the same directory. You can use it to copy (partial) sections from the default configuration file whenever you want to make changes only for that application specifically.</p>
<h3 id="use-of-the-configuration-file">Use of the Configuration file</h3>
<p>What you can modify in a configuration file:</p>
<ul>
<li>the tracker to use for motion compensation</li>
<li>the strength and the number of filtering stages for both translational and rotational filters</li>
<li>keyboard inputs (e.g. to activate/deactivate or recalibrate motion compensation during runtime)<br />
<strong>Note that all keys and values in the configuration file(s) are case sensitive. That means all <a href="#list-of-keyboard-bindings">keyboard shortcuts</a> must only contain capital letters, numbers and/or underscores</strong></li>
</ul>
<h3 id="sections-in-configuration-file">Sections in configuration file</h3>
<ul>
<li><code>startup</code>: You can modify oxrmc's behaviour on application start, e.g. disable a specific feature by setting the corresponding key to 0.
<ul>
<li><code>enabled</code>: you can disable all functionality globally or for a single application. Note that you cannot enable a single application if oxrmc is disabled globally in the default config file. Modifiying this setting requires an applcation restart.</li>
<li><code>physical_enabled</code>: initialization of physical tracker (motion controller or vive tracker) on startup can be skipped (e.g. if you're using a virtual tracker). Modifiying this setting requires an application restart.</li>
<li><code>overlay_enabled</code>: enable intitialization of the graphical overlay (for example if it's not required beacuse of using a physical tracker or if the position of the center of rotation is successfully setup and <code>use_cor_pos</code> = 1 is used). Changing this value requires the VR session to be restarted.</li>
<li><code>physical_early_init</code>: initialize physical tracker as soon instead of as late as possible. May be required in native OpenXR games / sims that do not support motion controllers input (e.g. iRacing). May avoid conflicts with other open xr layers (e.g. eye tracking in OpenXR toolkit). Modifiying this setting requires an applcation restart.</li>
<li><code>upside_down</code>: turn in-game coordinate system upside down by rotating it 180 degrees around the 'forward' axis. Necessary for correct orientation of virtual tracker and motion compensation in some games (e.g. iRacing). Changing this value requires the VR session to be restarted.</li>
<li><code>activate</code>: automatically activate motion compensation on application start and configuration reload.</li>
<li><code>activate_delay</code>: delay auto-activation by specified number of seconds. The required time for successful activation may vary, depending on application and tracker type used.</li>
<li><code>activate_countdown_</code>: enable audible countdown for the last 10 seconds before auto-activation. This is supposed to allow getting to neutral postion and timely centering of in-game view.</li>
</ul>
</li>
<li><code>tracker</code>: The following tracker <code>type</code> keys are available:
<ul>
<li><code>controller</code>: use either the left or the right motion controller as reference tracker. Valid options for the key <code>side</code> are <code>left</code> and <code>right</code> (<strong>Note that changing the side or switching between motion controller and vive tracker requires a restart of the vr session</strong>)</li>
<li><code>vive</code>: use a vive tracker as reference for motion compensation. The key <code>side</code> has to match the role assigned to the tracker. Valid options for that are:
<ul>
<li><code>handheld_object</code> - which hand (left, right, any) doesn't matter. Having more than one active vive tracker assigned to that role may lead to conflicts, though.</li>
<li><code>left_foot</code></li>
<li><code>right_foot</code></li>
<li><code>left_shoulder</code></li>
<li><code>right_shoulder</code></li>
<li><code>left_elbow</code></li>
<li><code>right_elbow</code></li>
<li><code>left_knee</code></li>
<li><code>right_knee</code></li>
<li><code>waist</code></li>
<li><code>chest</code></li>
<li><code>camera</code></li>
<li><code>keyboard</code>.</li>
</ul>
</li>
<li><code>connection_timeout</code> sets the time (in seconds) the tracker needs to be unresponsive before motion compensation is automatically deactivated. Setting a negative value disables automatic deactivation.</li>
<li><code>connection_check</code> is only relevant for virtual trackers and determines the period (in seconds) for checking wether the memory mapped file used for data input is actually still actively used. Setting a negative value disables the check</li>
<li><code>srs</code>: use the virtual tracker data provided by SRS motion software when using a Witmotion (or similar?) sensor on the motion rig.</li>
<li><code>flypt</code> use the virtual tracker data provided by FlyPT Mover.</li>
<li><code>yaw</code>: use the virtual tracker data provided by Yaw VR and Yaw 2. Either while using SRS or Game Engine.</li>
<li>the keys <code>offset_...</code>, <code>use_cor_pos</code> and <code>cor_...</code> are used to handle the configuration of the center of rotation (cor) for all available virtual trackers.</li>
<li><code>marker_size</code> sets the size of the cor / reference tracker marker displayed in the overlay. The value corresponds to the length of one double cone in cm.</li>
</ul>
</li>
<li><code>translational_filter</code> and <code>rotational_filter</code>: set the filtering magnitude (key <code>strength</code> with valid options between <strong>0.0</strong> and <strong>1.0</strong>) number of filtering stages (key <code>order</code>with valid options: <strong>1, 2, 3</strong>).<br />
The key <code>vertical_factor</code> is applied to translational filter strength in vertical/heave direction only (Note that the filter strength is multiplied by the factor and the resulting product of strength * vertical_factor is clamped internally between 0.0 and 1.0).</li>
<li><code>cache</code>: you can modify th cache used for reverting the motion corrected pose on frame submission:
<ul>
<li><code>use_eye_cache</code> - choose between calcuating eye poses (0 = default) or use cached eye poses (1, was default up until version 0.1.4). Either one might work better with some games or hmds if you encounter jitter with mc activated. You can also modify this setting (and subsequently save it to config file) during runtime with the corresponding shortcut below.</li>
<li><code>tolerance</code> - modify the time values are kept in cache for before deletion. This may affect eye calculation as well as cached eye positions.</li>
</ul>
</li>
<li><code>shortcuts</code>: can be used to configure shortcuts for different commands (See <a href="#list-of-keyboard-bindings">List of keyboard bindings</a> for valid values):
<ul>
<li><code>activate</code>- turn motion compensation on or off. Note that this implicitly triggers the calibration action (<code>center</code>) if that hasn't been executed before.</li>
<li><code>center</code> - recalibrate the neutral reference pose of the tracker</li>
<li><code>translation_increase</code>, <code>translation_decrease</code> - modify the strength of the translational filter. Changes made during runtime can be saved by using a save command (see below).</li>
<li><code>rotation_increase</code>, <code>rotation_decrease</code> = see above, but for rotational filter</li>
<li><code>offset_forward</code>, <code>offset_back</code>, <code>offset_up</code>, <code>offset_down</code>, <code>offset_right</code>, <code>offset_left</code> - move the center of rotation (cor) for a virtual tracker. The directions are aligned with the forward vector set with the <code>center</code> command. Changes made during runtime can be saved by using a save command (see below).</li>
<li><code>rotate_right</code>, <code>rotate_left</code> - rotate the aforementioned forward vector aroung the gravitational (yaw-)axis. Note that these changes cannot be saved. Therefore changing the offset position AFTER rotating manually and saving the offset values will result in the cor being a different offset position after relaoding those saved values.</li>
<li><code>toggle_overlay</code> - (de)activate graphical overlay displaying the reference tracker position(s) (See <a href="#graphical-overlay">Graphical overlay</a> for details).</li>
<li><code>toggle_cache</code> - change between calculated and cached eye positions.</li>
<li><code>save_config</code> - write current filter strength and cor offsets to global config file</li>
<li><code>save_config_app</code> - write current filter strength and cor offsets to application specific config file. Note that values in this file will precedent values in the global config file.</li>
<li><code>reload_config</code> - read in and apply configuration for current app from config files. For technical reasons motion compensation is automatically deactivated and the reference tracker pose is invalidated upon configuration reload.</li>
<li>Note that there are some immutable keyboard shortcuts:
<ul>
<li><code>ctrl + shift + alt + i</code>: logs your current interaction profile, which can be useful when debugging issues with a physical tracker.</li>
<li><code>ctrl + shift + alt + t</code>: logs the current pose of the reference tracker, can also be used for the purpose of troubleshooting.</li>
</ul>
</li>
</ul>
</li>
<li><code>debug</code>: For debugging reasons you can check, if the motion compensation functionality generally works on your system without using tracker input from the motion controllers at all by setting <code>testrotation</code> value to <code>1</code> and reloading the configuration. You should be able to see the world rotating around you after pressing the activation shortcut.<br />
<strong>Beware that this can be a nauseating experience because your eyes suggest that your head is turning in the virtual world, while your inner ear tells your brain otherwise. You can stop motion compensation at any time by pressing the activation shortcut again!</strong></li>
</ul>
<h2 id="using-a-virtual-tracker">Using a virtual tracker</h2>
<p>To use a virtual tracker (as opposed to a physical device) set parameter <code>tracker_type</code> according to the motion software that is providing the data for motion compensation on your system:</p>
<ul>
<li><code>yaw</code>: Yaw Game Engine (or Sim Racing Studio when using rotational data provided by Yaw VR or Yaw 2)</li>
<li><code>srs</code>: Sim Racing Studio, using a Witmotion sensor</li>
<li><code>flypt</code>: FlyPT Mover</li>
</ul>
<h3 id="calibrate-virtual-tracker">Calibrate virtual tracker</h3>
<p>To enable OXRMC to correlate translation and rotation of the rig to the virtual space correctly when using a virtual tracker, you have to provide the information where the center of rotation (cor) of your motion rig is positioned and which way is forward. This can be done with the following steps:</p>
<ol start="0">
<li>Calculate, measure or estimate the distance between your headset and the center of rotation of your motion rig in forward/backward, up/down and left/right direction (I was told most 6 dof rigs rotate around the bottom of the seat but your mileage may vary).</li>
<li>Enter the offset values in the config file</li>
<li>Start the OpenXR application of your choice</li>
<li>Bring your motion rig in neutral position</li>
<li>Sit in your rig</li>
<li>put your headset on and face forward (~ direction surge). Potential rotation of the hmd on roll and pitch angle is ignored for the calculation</li>
<li>issue the calibration command by activating the <code>center</code> shortcut. You can also do this implicitly by activating motion compensation if you haven't (re)calibrated since last loading of the configuration.</li>
</ol>
<ul>
<li>If you're unable to locate the cor of your rig, try out the method described in the <a href="#virtual-tracker">according troubleshooting section</a></li>
<li>You may have to invert some of the rotations/translations on output side to get them compensated properly. <strong>For new users it's strongly recommended to use some artificial telemetry (joystick input, sine wave generator, etc.) and testing one degree of freedom at at time</strong></li>
<li>If you're using YawVR Game Engine you can also use the parameters <code>Head Distance</code> and <code>Height</code> in its Motion Compensation tab to specify the offset of the cor. Head distance is basically equal to <code>offset_forward</code> in the configration file. But note that the height parameter is measured upwards from the bottom of your playspace, so you'll need to have that setup correctly in order to use that feature.</li>
</ul>
<h3 id="saving-and-the-cor-location">Saving and the cor location</h3>
<p>The current position and orientation of the cor is part of the configuration and can be saved to the (global or app-specific) config file. When your satisfied with the current setting you can set the config key <code>use_cor_pos</code> to <code>1</code>. This causes the cor position to be loaded from the config file when calibrating instead of being determined using the hmd position and the offset values.<br />
<strong>Note that this functionality may not work with all HMD vendors. Setting up the playspace in the VR runtime configuration of your hmd might help to get this working correctly. Rumor has it that some HMDs need to be started/initialized at the exact same location for the playspace coordinates to be consistent in between uses.</strong><br />
Feedback on success or failure of this functionality using different VR systems is very welcome and can be made via <a href="#contact">discord server</a> of the project.</p>
<h2 id="running-your-application">Running your application</h2>
<ol>
<li>make sure your using OpenXR as runtime in the application you wish to use motion compensation in</li>
<li>start application</li>
<li>center the in-app view</li>
<li>activate the motion controller you configured and mount it on your motion rig</li>
<li>bring your motion rig to neutral position</li>
<li>Reset the ingame view if necesary</li>
<li>press the <code>activate</code> shortcut (<strong>CTRL</strong> + <strong>INSERT</strong> by default). This implicitly sets the neutral reference pose for the tracker</li>
</ol>
<ul>
<li>if necessary you can recalibrate the tracker by pressing the <code>center</code> shortcut (<strong>CTRL</strong> + <strong>DEL</strong> by default) while the motion rig is in neutral position</li>
<li>you can increase or decrease the filter strength of translational and rotational filters</li>
<li>you can modify the cor offset when currently using a virtual tracker</li>
<li>after modifying filter strength or cor offset for virtual tracker you can save your changes to the default configuration file</li>
<li>after modifying the config file(s) manually you can use the <code>reload_config</code> shortcut (<strong>CTRL</strong> + <strong>SHIFT</strong> + <strong>L</strong> by default) to restart the OXRMC software with the new values.</li>
</ul>
<h3 id="graphical-overlay">Graphical overlay</h3>
<p>You can enable/disable the overlay using the <code>toggle_overlay</code> shortcut. It displays a marker in your headset view for:</p>
<ul>
<li>the current neutral position of the reference tracker. <strong>Note that the position of the marker does not represent the cor position prior to calibration</strong>
<ul>
<li>for a virtual tracker the neutral position corresponds to the center of rotation currently configured. The marker uses the following color coding:
<ul>
<li>blue points upwards</li>
<li>green points forward</li>
<li>red points to the right</li>
<li>if blue and red are pointing in the opposite direction, try setting <code>upside_down</code> to 1 in the <code>startup</code> section of the config file of the corresponding application (or check if it is set to 1 inadvertently).</li>
</ul>
</li>
<li>for a physical tracker the orientation of the marker is depending on the runtime implementation</li>
</ul>
</li>
<li>the current tracker position, if mc is currently active. This marker uses:
<ul>
<li>cyan instead of blue</li>
<li>yellow instead of green</li>
<li>magenta istead of red</li>
</ul>
</li>
</ul>
<h3 id="connection-loss">Connection Loss</h3>
<p>OXRMC can detect if a reference tracker isn't available anymore, if:</p>
<ul>
<li>for a physical tracker: the runtime lost tracking of a motion controller / vive tracker</li>
<li>for a virtual tracker: the memory mapped file providing data for a virtual tracker is removed by windows due to inactivity of the sender</li>
</ul>
<p>After detecting a loss of connection a configurable timeout period is used (<code>connection_timeout</code>), allopwing two possible outcomes:</p>
<ul>
<li>the connection is reastablished within the timeout period: motion compensation is continued (and the next potential connection loss resets the timeout period)</li>
<li>the connection stays lost and motion compensation is automatically deactivated. At that point you get an audible warning about connection loss.
<ul>
<li>If you try to reactivate and the tracker is available again, motion compensation is resumed (without the need for tracker recalibration)</li>
<li>Otherwise, the error feedback is repeated and motion compensation stays deactivated. When using a virtual tracker and having connection problems, you can use the MMF Reader app (see below) to cross check existence and current output values of the memory mapped file used for data exchange.</li>
</ul>
</li>
</ul>
<h2 id="troubleshooting">Troubleshooting</h2>
<p>Upon activating any shortcut you get audible feedback, corresponding to the performed action (or an error, if something went wrong).
If you're getting 'error' or no feedback at all, check for error entries (search for keyword 'error') in the log file at <strong>...\Users&lt;Your_Username&gt;\AppData\Local\OpenXR-MotionCompensation\OpenXR-MotionCompensation.log</strong>.</p>
<h3 id="recentering-in-game-view">Recentering in-game view</h3>
<p>If you recenter the in-app view during a session the reference pose is reset by default. Therefore you should only do that while your motion rig is in neutral position. It is possible (depending on the application) that this automatic recalibration is not triggered, causing the view and reference pose to be out of sync and leading to erroneous motion compensation. You should do the following steps to get this corrected again:</p>
<ol>
<li>deactivate motion compensation by pressing the <code>activate</code> shortcut</li>
<li>bring your motion rig to neutral position. Face forward if yout using a virtual tracker</li>
<li>recalibrate by pressing the <code>center</code> shortcut</li>
<li>reactivate motion compensation by pressing the <code>activate</code> shortcut</li>
</ol>
<h3 id="virtual-tracker">Virtual tracker</h3>
<p>When using a <strong>virtual tracker</strong> and the audible feedback says 'motion compensation activated' but you don't get motion compensation as you would expect
Use the <a href="#mmf-reader">MmfReader App</a> to make sure oxrmc is actually receiving data from the motion software.</p>
<ul>
<li>check center of rotation position</li>
<li>activate graphical overlay</li>
<li>verify position and orientation of the marker
If don't have a clue where the cor of your motion rig is supposed to be, you can try this procedure, that should work for most motion rig setups (you can watch a <a href="https://youtu.be/mIIlIlV-B_4">video of a similar procedure at YouTube</a>):</li>
</ul>
<ol>
<li>Find a way to feed your motion software with artificial rotational telemetry (e.g. Joystick mode in the Setup section of SRS, a sine wave generator for FlyPT Mover or Gamepad / DirectInput plugin for YawVR Game Engine.</li>
<li>Calibrate your cor (ctrl+del by default) as described in <a href="#calibrate-virtual-tracker">here</a> and activate motion compenation</li>
<li>Find the right height
<ol>
<li>start rolling fully to the right while keeping the head still (in reference to the seat) and check if your ingame position is moving.</li>
<li>if your view is moved to the right, lower your cor position (ctrl+page down), if it's moving left lift it up (ctrl + page up)</li>
<li>rinse &amp; repeat until your in-game position does not move when rolling</li>
</ol>
</li>
<li>Set the forward distance
<ol>
<li>start pitching fully backward do the same as for roll, but this time check if you're moved up or down in game</li>
<li>if your position is rising move the cor backwards, if it's lowering move it forward</li>
<li>rinse &amp; repeat until your in-game position does not move when rolling</li>
</ol>
</li>
<li>Save your configuration (ctrl + shift + s), once you got your cor dialed in. That causes the new offset values as well as the current cor position to be written into the config file for later use.</li>
</ol>
<h3 id="physical-tracker">Physical tracker</h3>
<ul>
<li>Make sure the tracker/controller doesn't go into standby mode</li>
<li>Place a lighthouse based tracker to have line of sight to as many basestations as possible</li>
<li>If you're experiencing tracking issues on strong vibrations (e.g. transducer) on the rig, try to find a better mounting spot or tune vibrations down.</li>
</ul>
<p>You can always request help on the <a href="https://discord.gg/BVWugph5XF">Discord server</a></p>
<ul>
<li>provide as much <strong>information</strong> as possible about your setup and the isssue you're having, including:
<ul>
<li>log file</li>
<li>tracker type</li>
<li>hmd</li>
<li>game(s)</li>
<li>usin OpenComposite o</li>
</ul>
</li>
</ul>
<h2 id="additional-notes">Additional Notes</h2>
<ul>
<li>If the motion controller cannot be tracked for whatever reason (or if the memory mapped file containing the motion data for a virtual tracker cannot be found or accessed) when activating motion compensation or recalibrating the tracker pose, the API layer is unable to set the reference pose and motion compensation is (or stays) deactivated.</li>
</ul>
<h3 id="mmf-reader">MMF Reader</h3>
<p>The software package includes a small app called MMF Reader which allows you to display the content of the memory mapped file used for virtual trackers. Just execute it from windows start menu or use the executable in the installation directory and select the kind of tracker you're using from the dropdown menu.</p>
<ul>
<li>If the memory mapped file does not exist and therefore no values can be read, all the values are displaying an <code>X</code>.</li>
<li>Otherwise the current values are displayed using arc degree as unit for rotations and meter for translations.</li>
</ul>
<h3 id="logging">Logging</h3>
<p>The motion compensation layers logs rudimentary information and errors in a text file located at <strong>...\Users&lt;Your_Username&gt;\AppData\Local\OpenXR-MotionCompensation\OpenXR-MotionCompensation.log</strong>. After unexpected behaviour or a crash you can check that file for abormalities or error reports.</p>
<p>If you encounter repeatable bugs or crashes you can use the Windows Performance Recorder Profile (WPRP) tracelogging in combination with the configuration contained within <code>scripts\Trace_OpenXR-MotionCompensation.wprp</code> to create a more detailed protocol.</p>
<p><a href="https://docs.microsoft.com/en-us/windows/win32/tracelogging/trace-logging-portal">Tracelogging</a> can become very useful to investigate user issues.</p>
<p>To capture a trace for the API layer:</p>
<ul>
<li>start the OpenXR application</li>
<li>Open a command line prompt or powershell in administrator mode and in a folder where you have write permissions</li>
<li>Begin recording a trace with the command: <code>wpr -start path\to\Trace_OpenXR-MotionCompensation.wprp -filemode</code></li>
<li>Leave that command prompt open</li>
<li>Reproduce the crash/issue</li>
<li>Back to the command prompt, finish the recording with: <code>wpr -stop arbitrary_name_of_file.etl</code></li>
<li>These files are highly compressible!</li>
</ul>
<p>You can send the trace file to the developer or use an application such as <a href="https://apps.microsoft.com/store/detail/tabnalysis/9NQLK2M4RP4J?hl=en-id&amp;gl=ID">Tabnalysis</a> to inspect the content yourself.</p>
<h2 id="list-of-keyboard-bindings">List of keyboard bindings</h2>
<p>To combine multiple keys for a single shortcut they need to be separated by '+' with no spaces in between the key descriptors.</p>
<p>List of supported shortcut key names:</p>
<table>
<thead>
<tr>
<th style="text-align: left;">Name</th>
<th style="text-align: left;">Key</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;"><code>SHIFT</code></td>
<td style="text-align: left;">shift key</td>
</tr>
<tr>
<td style="text-align: left;"><code>CTRL</code></td>
<td style="text-align: left;">ctrl key</td>
</tr>
<tr>
<td style="text-align: left;"><code>ALT</code></td>
<td style="text-align: left;">alt key</td>
</tr>
<tr>
<td style="text-align: left;"><code>LSHIFT</code></td>
<td style="text-align: left;">left shift key</td>
</tr>
<tr>
<td style="text-align: left;"><code>RSHIFT</code></td>
<td style="text-align: left;">right shift key</td>
</tr>
<tr>
<td style="text-align: left;"><code>LCTRL</code></td>
<td style="text-align: left;">left ctrl key</td>
</tr>
<tr>
<td style="text-align: left;"><code>RCTRL</code></td>
<td style="text-align: left;">right ctrl key</td>
</tr>
<tr>
<td style="text-align: left;"><code>LALT</code></td>
<td style="text-align: left;">left alt key</td>
</tr>
<tr>
<td style="text-align: left;"><code>RALT</code></td>
<td style="text-align: left;">right alt key</td>
</tr>
<tr>
<td style="text-align: left;"><code>0</code>- <code>9</code></td>
<td style="text-align: left;">numerical key</td>
</tr>
<tr>
<td style="text-align: left;"><code>A</code>- <code>Z</code></td>
<td style="text-align: left;">alphbetical key</td>
</tr>
<tr>
<td style="text-align: left;"><code>BACKQUOTE</code></td>
<td style="text-align: left;">`~ key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>TAB</code></td>
<td style="text-align: left;">tabulator key</td>
</tr>
<tr>
<td style="text-align: left;"><code>CAPS</code></td>
<td style="text-align: left;">caps lock key</td>
</tr>
<tr>
<td style="text-align: left;"><code>PLUS</code></td>
<td style="text-align: left;">+ key (any country)</td>
</tr>
<tr>
<td style="text-align: left;"><code>MINUS</code></td>
<td style="text-align: left;">- key (any country)</td>
</tr>
<tr>
<td style="text-align: left;"><code>OPENBRACKET</code></td>
<td style="text-align: left;">[{ key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>CLOSEBRACKET</code></td>
<td style="text-align: left;">]} key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>SEMICOLON</code></td>
<td style="text-align: left;">;: key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>QUOTE</code></td>
<td style="text-align: left;">'&quot; key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>BACKSLASH</code></td>
<td style="text-align: left;">\| key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>COMMA</code></td>
<td style="text-align: left;">, key (any country)</td>
</tr>
<tr>
<td style="text-align: left;"><code>PERIOD</code></td>
<td style="text-align: left;">. key (any country)</td>
</tr>
<tr>
<td style="text-align: left;"><code>SLASH</code></td>
<td style="text-align: left;">/? key (US)</td>
</tr>
<tr>
<td style="text-align: left;"><code>BACK</code></td>
<td style="text-align: left;">backspace key</td>
</tr>
<tr>
<td style="text-align: left;"><code>CLR</code></td>
<td style="text-align: left;">clr key</td>
</tr>
<tr>
<td style="text-align: left;"><code>RETURN</code></td>
<td style="text-align: left;">return key</td>
</tr>
<tr>
<td style="text-align: left;"><code>ESC</code></td>
<td style="text-align: left;">esc key</td>
</tr>
<tr>
<td style="text-align: left;"><code>SPACE</code></td>
<td style="text-align: left;">space key</td>
</tr>
<tr>
<td style="text-align: left;"><code>LEFT</code></td>
<td style="text-align: left;">cursor left key</td>
</tr>
<tr>
<td style="text-align: left;"><code>UP</code></td>
<td style="text-align: left;">cursor up key</td>
</tr>
<tr>
<td style="text-align: left;"><code>RIGHT</code></td>
<td style="text-align: left;">cursor right key</td>
</tr>
<tr>
<td style="text-align: left;"><code>DOWN</code></td>
<td style="text-align: left;">cursor down key</td>
</tr>
<tr>
<td style="text-align: left;"><code>INS</code></td>
<td style="text-align: left;">ins key</td>
</tr>
<tr>
<td style="text-align: left;"><code>DEL</code></td>
<td style="text-align: left;">del key</td>
</tr>
<tr>
<td style="text-align: left;"><code>HOME</code></td>
<td style="text-align: left;">home key</td>
</tr>
<tr>
<td style="text-align: left;"><code>END</code></td>
<td style="text-align: left;">end key</td>
</tr>
<tr>
<td style="text-align: left;"><code>PGUP</code></td>
<td style="text-align: left;">page up key</td>
</tr>
<tr>
<td style="text-align: left;"><code>PGDN</code></td>
<td style="text-align: left;">page down key</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM0</code></td>
<td style="text-align: left;">0 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM1</code></td>
<td style="text-align: left;">1 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM2</code></td>
<td style="text-align: left;">2 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM3</code></td>
<td style="text-align: left;">3 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM4</code></td>
<td style="text-align: left;">4 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM5</code></td>
<td style="text-align: left;">5 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM6</code></td>
<td style="text-align: left;">6 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM7</code></td>
<td style="text-align: left;">7 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM8</code></td>
<td style="text-align: left;">8 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUM9</code></td>
<td style="text-align: left;">9 key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMLOCK</code></td>
<td style="text-align: left;">numlock key</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMDIVIDE</code></td>
<td style="text-align: left;">/ key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMMULTIPLY</code></td>
<td style="text-align: left;">* key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMSUBTRACT</code></td>
<td style="text-align: left;">- key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMADD</code></td>
<td style="text-align: left;">+ key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMDECIMAL</code></td>
<td style="text-align: left;">. key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>NUMSEPARATOR</code></td>
<td style="text-align: left;">separator key on NUM</td>
</tr>
<tr>
<td style="text-align: left;"><code>F1</code></td>
<td style="text-align: left;">F1 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F2</code></td>
<td style="text-align: left;">F2 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F3</code></td>
<td style="text-align: left;">F3 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F4</code></td>
<td style="text-align: left;">F4 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F5</code></td>
<td style="text-align: left;">F5 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F6</code></td>
<td style="text-align: left;">F6 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F7</code></td>
<td style="text-align: left;">F7 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F8</code></td>
<td style="text-align: left;">F8 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F9</code></td>
<td style="text-align: left;">F9 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F10</code></td>
<td style="text-align: left;">F10 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F11</code></td>
<td style="text-align: left;">F11 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>F12</code></td>
<td style="text-align: left;">F12 key</td>
</tr>
<tr>
<td style="text-align: left;"><code>PRTSC</code></td>
<td style="text-align: left;">print screen key</td>
</tr>
<tr>
<td style="text-align: left;"><code>SCROLL</code></td>
<td style="text-align: left;">scroll lock key</td>
</tr>
<tr>
<td style="text-align: left;"><code>PAUSE</code></td>
<td style="text-align: left;">pause key</td>
</tr>
<tr>
<td style="text-align: left;"><code>SELECT</code></td>
<td style="text-align: left;">select key</td>
</tr>
<tr>
<td style="text-align: left;"><code>PRINT</code></td>
<td style="text-align: left;">print key</td>
</tr>
<tr>
<td style="text-align: left;"><code>HELP</code></td>
<td style="text-align: left;">help key</td>
</tr>
<tr>
<td style="text-align: left;"><code>EXEC</code></td>
<td style="text-align: left;">execute key</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_A</code></td>
<td style="text-align: left;">A button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_B</code></td>
<td style="text-align: left;">B button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_X</code></td>
<td style="text-align: left;">X button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_Y</code></td>
<td style="text-align: left;">Y button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_SHOULDER</code></td>
<td style="text-align: left;">right shoulder button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_SHOULDER</code></td>
<td style="text-align: left;">left shoulder button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_TRIGGER</code></td>
<td style="text-align: left;">left trigger button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_TRIGGER</code></td>
<td style="text-align: left;">right trigger button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_DPAD_UP</code></td>
<td style="text-align: left;">digital pad up on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_DPAD_DOWN</code></td>
<td style="text-align: left;">digital pad down on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_DPAD_LEFT</code></td>
<td style="text-align: left;">digital pad left on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_DPAD_RIGHT</code></td>
<td style="text-align: left;">digital pad right on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_START</code></td>
<td style="text-align: left;">start button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_VIEW</code></td>
<td style="text-align: left;">view button on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_THUMBSTICK_BUTTON</code></td>
<td style="text-align: left;">left thumbstick pressed on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_THUMBSTICK_BUTTON</code></td>
<td style="text-align: left;">right thumbstick pressed on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_THUMBSTICK_UP</code></td>
<td style="text-align: left;">left thumbstick up on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_THUMBSTICK_DOWN</code></td>
<td style="text-align: left;">left thumbstick down on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_THUMBSTICK_RIGHT</code></td>
<td style="text-align: left;">left thumbstick left on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_LEFT_THUMBSTICK_LEFT</code></td>
<td style="text-align: left;">left thumbstick right on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_THUMBSTICK_UP</code></td>
<td style="text-align: left;">right thumbstick up on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_THUMBSTICK_DOWN</code></td>
<td style="text-align: left;">right thumbstick down on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_THUMBSTICK_RIGHT</code></td>
<td style="text-align: left;">right thumbstick left on gamepad</td>
</tr>
<tr>
<td style="text-align: left;"><code>GAMEPAD_RIGHT_THUMBSTICK_LEFT</code></td>
<td style="text-align: left;">right thumbstick right on gamepad</td>
</tr>
</tbody>
</table>
</content>
</body>
</html>

BIN
motion_sim/end-cap.STL Normal file

Binary file not shown.

BIN
motion_sim/test.FCStd Normal file

Binary file not shown.