The _vrconfig.txt file is a text-based configuration file that customizes VR interactions for your aircraft.
VR Configurations are aircraft-specific which means each ACF requires its own configuration file. While VR Configurations are not required, they are strongly encouraged. Aircraft that do not have a VR Configuration will still load and still work, even with VR enabled, however, there will be no hotspots to make it easy for the user to get back into the pilot seat, and there will be no customization allowing the VR controllers to be used to their fullest potential.
The VR Configuration name needs to match the prefix of the ACF file, with _vrconfig.txt appended to the end. For example, to make a VR config for Cessna_172SP.acf, the file needs to be called Cessna_172SP_vrconfig.txt. This file must exist in the same directory as the ACF file.
The _vrconfig.txt file is a text file – Unix or Windows line endings are legal, blank lines are allowed after the header, and the character set should be UTF-8.
The header of the file should be
followed by the directives listed below.
Hotspots are predefined locations that are used to precisely orient the VR user when selected. They are commonly used on the pilot and co-pilot seats so that users can quickly position themselves accurately in the seats.
Each hotspot block defines a single hotspot on or around the aircraft. You must use a matched pair of BEGIN_TELEPORT_HOTSPOT and END_TELEPORT_HOTSPOT. In this block you must have:
- Exactly one Axis-Aligned-Bounding-Box (AABB)
- Exactly one XYZ location
- Exactly one Psi, Theta, and Phi orientation respectively.
Note: Unless the REF_POINT_ACF directive is set, all units are in Aircraft Coordinates – meters with the origin at the aircraft CG and the positive Z axis pointing aft. This is not the same as the English units used in Plane-Maker.
REF_POINT_ACF <y_meters> <z_meters> (V12 and later)
If this directive appears in the VRCONFIG, the hotspot location origin for AABB and PRESET_XYZ are no longer tied to the aircraft’s CG but instead moves to some offset from the aircraft’s authoring point in Plane-Maker. Typically artists will put the reference point of the aircraft at the tip of the nose or tail and it stays there throughout the aircraft’s existence. This makes it a more useful reference point for coordinates than the aircraft’s CG which might change as authors gather newer and more accurate data to model the aircraft.
There are two main uses of this directive. First, if the VRCONFIG is being done for the very first time, setting this directive tells the sim to just use the authoring point as the origin so it’ll never be tied to the CG. You can leave the Y/Z coordinates blank and the sim will assume you mean 0.0 0.0. The second main use is for VRCONFIGs that have already been done for an aircraft that is now having it’s CG moved. Rather than have to adjust every coordinate in the VRCONFIG, you can use this directive to tell the sim that the origin should be at the OLD CG’s location by telling it where the OLD CG was relative to the aircraft’s authoring point. For example, if the OLD CG was at a Y/Z of 3.28084ft/-6.56168ft (remember, PlaneMaker uses FEET for its units) then you could add REF_POINT_ACF 1.0 -2.0 (which is the old CG location, converted from feet to meters) as a directive to the VRCONFIG which will allow the CG to move but the reference point for the file to stay at the OLD CG.
BEGIN_TELEPORT_HOTSPOT <Hotspot Type> <Name>
This begins the definition of a new teleport hotspot. All hotspot properties must be specified after this directive and before the matched END_TELEPORT_HOTSPOT directive. The legal types of hotspots are ‘SITTING’ and ‘STANDING’. A sitting hotspot places the user’s head at the XYZ location. A standing hotspot places the user’s feet at the XYZ location. The name property is useful for debugging purposes.
This defines the end of a given teleport hotspot. Each hotspot must be “ended” before anything else in the file occurs, and before the file ends.
AABB <minx> <miny> <minz> <maxx> <maxy> <maxz>
This adds an axis-aligned bounding box (in aircraft coordinates, that is +X = right, +Y = up, +Z = aft) in meters around the CG of the aircraft. When the teleport beam lands inside this box, if the user ends the teleport, this hotspot will be used to position the user.
PRESET_XYZ <x> <y> <z>
This sets the location of the user to the location X, Y, Z in meters, relative to the default CG of the aircraft; X is right, Y is up, Z is aft. A sitting hotspot places the user’s head at the XYZ location. A standing hotspot places the user’s feet at the XYZ location.
PRESET_PSI <deg 0 – 360>
This sets the rotation orientation (rotating about the Y-axis) of the user’s view in degrees. 0 degrees is facing forward in the aircraft, 90 would look toward the right wing, 180 degrees would be looking back at the tail etc.
PRESET_THE <deg -90 – 90>
This sets the pitch orientation (rotating about the X-axis) of the user’s view in degrees. 0 degrees is level. 90 would look straight up at the sky. -90 would look down at the ground.
PRESET_PHI <deg -180 – 180>
This sets the tilt orientation (rotating about the Z-axis) of the user’s view in degrees. 0 degrees is upright. -90 would be like tilting their left ear to their shoulder. 90 would be like tilting their right ear to their shoulder.
Some aircraft manipulators need more information than is currently available in the OBJ itself in order to function optimally with VR Controllers. The most common examples of these are knobs and switches. With a mouse, knobs usually move one detent for each click. With a VR controller, however, X-Plane needs to know how much rotation is necessary in order to move the knob to the next detent. For linear knobs like lighting rheostats, this can be a fraction of a degree. For more coarse knobs like a fuel selector, you may want to require 60 degrees of rotation. There are other reasons to specialize manipulators such as changing their behavior entirely. For example, if the default aircraft manipulator uses commands to increment something by single degrees, but you want a smoother feel to the knob, you may want to redefine the manipulator to use a dataref to increment by fractions of a degree.
It’s important to note that customizations done with this file ONLY affect VR controllers. They will not change mouse or joystick hardware functionality.
BEGIN_MANIP <manip type> <cmnd1/dref1> <cmnd2/dref2> <tooltip>
This begins the manipulator block that defines the EXISTING aircraft OBJ manipulator to be customized. All manipulator properties must be specified AFTER this directive and before the matched END_MANIP directive. This line essentially contains the unique pieces of the OBJ manipulator for it to be looked up.
The manipulator type needs to match the type specified in the OBJ but without the ‘ATTR_manip_’. For example, if the OBJ has an ATTR_manip_command_axis, the type (for the purposes of this file) should be ‘command_axis’. The cmnd1/dref1 and cmnd2/dref2 should match those that exist in the OBJ manipulator definition. If the manipulator needs only one command/dataref, then cmnd2/dref2 can be omitted completely.
Lastly, to disambiguate two manipulators that have the exact same type and act on the same commands/datarefs, an optional tooltip can be used. This is common with Yoke manipulators since there are usually two yokes for the pilot and copilot and they typically act on the same datarefs. Again, if the tooltip is unnecessary to find a manipulator that is unambiguous and unique, it can be omitted completely.
The manipulator block will match only one manipulator – if more than one manipulator in the OBJ matches the specification, only one will be remapped; use more information (E.g. tooltips) when you need to remap manipulators that are otherwise ambiguous.
This marks the end of a given manipulator block. Each manipulator block must be “ended” before anything else in the file occurs, and before the file ends.
ACTION axis_knob <v1 min> <v1 max> <dx> <dref1>
This tells the VR system that this manipulator should be changed to an axis_knob manipulator and used instead of the original manipulator. This is useful if you want to act on the dataref instead of a command in VR mode to have finer control over the knob’s increment/decrement amounts. DX specifies the amount of change applied to the dataref for each action. Use DEG_PER_ACTION to set the amount of wrist rotation needed for an action to fire.
ACTION axis_switch_up_down <v1 min> <v1 max> <dx> <dref1> (V12 and later)
This tells the VR system that this manipulator should be changed to an ATTR_manip_axis_switch_up_down manipulator and used instead of the original manipulator. This is useful if you want to act on a dataref instead of a command in VR mode to have finer control over the Up/Down switch’s increment/decrement amounts. DX specifies the amount of change applied to the dataref for each action. Use SWITCH_THRESHOLD to set the amount of wrist deflection/movement needed for an action to fire.
ACTION axis_switch_left_right <v1 min> <v1 max> <dx> <dref1> (V12 and later)
See ACTION axis_switch_up_down for details. It’s exactly the same except in the horizontal direction.
ACTION drag_xy four_arrows <dx> <dy> <v1min> <v1max> <v2min> <v2max> <dref1> <dref2> <tooltip>
This tells the VR system that this manipulator should be changed to a drag_xy manipulator and used instead of the original manipulator. This is usually used to override the show/hide Yoke manipulator to instead make it behave as if the user has grabbed the yoke to begin using it.
ACTION command_axis <vx> <vy> <vz> <cmnd1> <cmnd2> (V12 and later)
This tells the VR system that this manipulator should be changed to an ATTR_manip_command_axis manipulator and used instead of the original manipulator. This is useful for mechanical things that have two states that you want to move through with a rest in between. For example, consider an elevator trim switch that’s spring loaded in the up and down positions so it always recenters. This manipulator coupled with a HOLD_MANIP flag will get you that behavior.
ACTION command_knob <cmnd1> <cmnd2> (V12 and later)
This tells the VR system that this manipulator should be changed to an ATTR_manip_command_knob manipulator and used instead of the original manipulator. This is useful if you want the mechanical thing to perform one command in a direction and another command if rotated in the opposite direction.
This tells the system how many degrees of wrist rotation is necessary before a knob manipulator will be acted upon. Another way of thinking about it is how far does the VR controller need to be rotated before the manipulator will fire as if the mouse was clicked once.
SWITCH_THRESHOLD <angle threshold deg> <offset thresh meter>
Similar to DEG_PER_ACTION for knobs, SWITCH_THRESHOLD tells the system how much wrist tilt or motion is necessary to trigger a command. This is useful for things dials like the vertical speed dial on an airliner. The angle in degrees tells the system how many degrees of tilt are necessary before triggering the command. The offset threshold in meters tells the system how much motion should exist before triggering the command. This allows the user to lift/lower their arm to operate the dial instead of tilting their wrist.
This tells the system that the knob manipulator should wrap. Examples of knobs that should wrap would include the course knob or heading bug. Examples of knobs that should not wrap are lighting knobs and volume controls.
This tells the system that the knob/switch manipulator should hold down commands continuously while it is not in motion. Without this, commands are issued once for each ‘click’ of the switch or knob; with this, a command is held until the knob/switch is released or moved again. Do not use this for manipulators that use datarefs. It is only intended for command manipulators.
Starter keys and spring-loaded knobs and switches often require the HOLD_MANIP directive as they will return to the off position when not held.
INVERT_MANIP (V12 and later)
This tells the system that the knob/switch manipulator should be inverted in the way it processes commands. For example, switches are expected to be UP in the ‘on’ position and DOWN in the ‘off’ position but some switches just aren’t modeled that way or the real switch is actually mounted upside down. With this flag, you can reverse the behavior to match real life without having to change the command order in the OBJ.
DISABLE_VISUALS (V12 and later)
This tells the system that it should not draw any kind of feedback visuals during manipulator use. Some manipulators such as axis manipulators visualize the axis while a user interacts with it. With this flag, that drawing will be disabled. This does not affect the drawing of the manipulator geometry BEFORE interaction.
JOYSTICK_MANIP <pitch min deg> <pitch max deg> <roll min deg> <roll max deg>
This tells the system that the manipulator is one that should be treated like a real-world joystick control (like those found on Airbuses and the CirrusJet). The data here will only become active if the user has enabled “Realistic” mode for their VR Yokes. The pitch and roll mins and maxes define the range of tilting motion in degrees of the VR controller that should be mapped to the full range of motion of the flight controls.
YOKE_MANIP_TRANSLATE <pitch trans axis min x> <pitch trans axis min y> <pitch trans axis min z> <pitch trans axis max x> <pitch trans axis max y> <pitch trans axis max z> <roll cent x> <roll cent y> <roll cent z> <roll min ang> <roll max ang>
This tells the system that the manipulator is one that should be treated like a real-world yoke control (like those found on a Cessna 172) where the pitch axis is a translation axis that slides back and forth and the roll axis is a rotation one like a steering wheel that rotates about a centroid. The data here will only become active if the user has enabled “Realistic” mode for their VR Yokes.
Pitch min and max x,y,z are in OBJ units and define the axis of translation for pitch; they can be taken directly from the translation axis used to animate your yoke. The length of the vector between these points defines how far the yoke moves from full nose up to full nose down, and is typically aligned along the Z axis.
Roll centroid x,y,z are also in OBJ units and define the point at which the yoke rotates around. This point should be somewhere on the center of the yoke, and can be taken from the static translation that precedes your yoke’s roll animation.
The roll axis defines the axis about which the yoke rolls, and can be taken from the axis of your roll animation directly. This should be a unit vector, and will typically be about the Z axis.
The roll min and max angles define the maximum travel in either direction from the “level” point, and can be taken from the end key frames of your roll animation.
YOKE_MANIP_ROTATE <pitch cent x> <pitch cent y> <pitch cent z> <pitch axis x> <pitch axis y> <pitch axis z> <pitch min deg> <pitch max deg> <roll cent x> <roll cent y> <roll cent z> <roll axis x> <roll axis y> <roll axis z> <roll min deg> <roll max deg>
This tells the system that the manipulator is one that should be treated like a real-world flight stick (like those found in a fighter jet or SuperCub) where the pitch and roll axis are attached to a single stick that is attached to a mount point that can be rotated forward and back as well as left and right about two centroids (that can be co-located).
Pitch and roll centroid x,y,z are in OBJ units and define the centroids about which the pitch and roll axis rotates – you can take them from the static translation that precedes your animation.
Pitch and rolls axis x,y,z define the unit vectors of the rotation axes for pitch and roll; they should be unit vectors and can be taken directly from your pitch and roll animations. Typically the pitch axis will be the X axis and the roll axis will be the Z axis.
The pitch and roll min and max degrees define the maximum amount of rotation that can exist in either direction, for both pitch and roll.
Note that you can use YOKE_MANIP_ROTATE for both flight sticks (like a helicopter or fighter) or for airliner-style column yokes. In the flight stick case, the rotation centroid is at the floor pivot for both axes. For an airliner yoke, the pitch centroid is on the floor but the roll centroid is on the yoke itself.
We do not recommend using YOKE_MANIP_ROTATE for very small side sticks because they are hard to control in VR; prefer JOYSTICK_MANIP instead.
15 comments on “Aircraft VR Configuration (_vrconfig.txt) File Format Specification”
Thank you so much for the clarity and non -technoid language of this article! Who authored this? – I suspect that Jennifer had a hand… great help – thank you LR team!
This is a great article. I plan to modify the vrconfig file to make the GPS knobs less sensitive when you change frequency or adjust the ICAO in the flight plan. Thank you for including these modifiers for developers and users!!
If there is no _vrconfig.txt file, will a VR load of 11.20 fail or hang up? My Log.txt file complains it can’t find iPad_vrconfig.txt, which seems to be the point at which the load fails. I started having this problem when I loaded the Oculus app after I bought a Rift. I didn’t have this problem with the vr beta, running iVRy, iTunes, and SteamVR with my iPhone.
I was wondering if there are plans to add more ACTION “manip type” options to change manipulators without having to globally change it in the obj. Right now ACTION axis knob works incredibly, but I’m having trouble with ACTION “any other manip” (not getting vr_config error, but crashes sim when using manip). Would love to change some throttle and mixture drag axis’s to “drag rotates”. Thanks!
I made a VERY simple config file for the Zenith Zodiac 650 that I imported from version 10. Loaded it into Plane Maker and saved it. Using joystick and rudder peddles for controls, the plane would fly off and leave me. I thought making a couple hotspots would be the solution once I found this.
I followed the directions, and then confirmed that I had it correct by referencing the included configs for the 172’s. It still didn’t work.
I looked in the logs. In consecutive statements it told me that it was loading the config file, it could not find the config file, that the config file was not valid, that it could not find the config file, and again that the config file was not valid. (Yes. It actually said it was not present and invalid twice.)
I test software for a living and I would open this as a Pri-1 bug, and have a long conversation with the developer until we come to terms. If you are going to bother to put something in a log file, make it useful. Could you give me a hint about what might not have been valid about it? I mean, you had to have looked at it and had some sort of decision logic of WHY it wasn’t valid. If nothing else you could spit the line that gave you indigestion back at me. “The file is invalid” is simply lazy programming.
I don’t mean to be preachy, but I run into this constantly and it just makes everyone’s (and by “everyone’s”, I mean “my”) life difficult.
It sounds like there may be a bug in the _logging code itself_. Please file a bug and include your full log.txt file and VR config file even though it’s useless – we may need to fix the logging so it is informative.
Is it possible to control the current hotspot in use via plugin? I would like to move the user to a specific hotspot using my plugin code.
It is not. At present, the VR APIs do not support moving the user at all.
Would it be possible to assign some haptic feedback to the VR controllers when grabbing a drag_xy manip? Mainly for yoke. If the same velocity/intesity haptic feedback code that is driving drag_rotate’s can be used as well on drag_axis, that would be a huge win for VR immersion…especially at the extents of the roll/pitch range, we would get a nice “clunk”…LOVE that in the drag_rotates.
Not part of the vrconfig file, but is there any documentation about how to implement the “MAGNET” object into a 3D cockpit? I am working with a developer and I have placed this object into the *cockpit.obj file manually and it works, but the developer is wanting to be able to use their in-house tools to keep this as part of their workflow and version tracking. I have not been able to find any documentation on this in the files on this site and would love to be able to provide the information how to do this in whatever 3D modeling tools they use.
A bit late to the party, but for anyone that reads from now on, the MAGNET directive is documented on the .OBJ file format document.
Hi to all Developer,
great Job implementing the VR.
Actually I am not flying, but have the HTC Vive and a friend of mine bought the Game an is hooked. I see him more frequent now :-).
As a Suggestion: would it be possible to enlarge the Instruments you select with the Laserpointer? It is currently very hard to read the Numbers and you have to move very Close to the Instrument in Order to See all details.
A simple HUD projection on the cockpitwindow or some sort of magnifying Lens would be great.
Maybe on XPlane 12 😉 ?
I am trying to make the yokes of some of mine aircrafts to be sensible for native VR controllers, creating vrconfig files. I don’t really know what I am missing here, I can’t understand why it doesn’t work, even if I follow all the manipulator instructions above.
Thank you if you can make a tutorial for implementing yoke’s on native VR controllers available.
Can you help me?
What if there is NO vrconfig.txt file for a given aircraft? Is there a way to have one automagically created–after setting the various settings in the aircraft, such as pilot/co-pilot seat settings, etc.?
Why do some aircraft crash X-Plane without the VR cofig.txt files present after deleting them and others don’t? I am not even using VR, but getting the message of problems with some VR config.txt files.