Writing Joystick Code: Part 3: Difference between revisions

Jump to navigation Jump to search
no edit summary
No edit summary
No edit summary
Line 9: Line 9:


-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
  To toggle the Parking brake, use this. Entire code-block shown. Non-repeatable button. (You have to specifically set <repeatable> to true if you want repeatable. It is assumed to be false.
  To toggle the Parking brake, use this. Entire code-block shown. Non-repeatable button. (You have to specifically set <repeatable> to true
if you want repeatable. It is assumed to be false.
   <button n="1">
   <button n="1">
     <desc>Toggle parking break</desc>
     <desc>Toggle parking break</desc>
Line 18: Line 19:
   </button>
   </button>
   
   
  This method can be used to toggle any property that is on/off. Use Debug - Browse Internal Properties to find suitable candidates. Also see getProp, setProp and setAll below.
  This method can be used to toggle any property that is on/off. Use Debug - Browse Internal Properties to find suitable candidates.  
Also see getProp, setProp and setAll below.
   
   
  Remember, it ''toggles'' the property, you can't use it to set the property into a specific state.
  Remember, it ''toggles'' the property, you can't use it to set the property into a specific state.
Line 101: Line 103:
   }
   }


Now lets pretend that we still want to increase x by 2 if it less than 5, and if it is 5 or more we want to add 1 to it. We use else. It looks like this
Now lets pretend that we still want to increase x by 2 if it less than 5, and if it is 5 or more we want to add 1 to it. We use else.
It looks like this
   if (x < 5) {
   if (x < 5) {
     x = x + 2
     x = x + 2
Line 117: Line 120:
   If (x < 5) then (x = x + 2) else if (x < 10) then (x = x + 1). If none of these are true then (x = x + 7). End of if clause.
   If (x < 5) then (x = x + 2) else if (x < 10) then (x = x + 1). If none of these are true then (x = x + 7). End of if clause.


We test for x < 5 first. If it fails we test for x < 10. If x , 5 succeeds we do (x = x + 2) and then move on past the end of if clause. So we can test for x < 5 and x < 10 in this way.
We test for x < 5 first. If it fails we test for x < 10. If x , 5 succeeds we do (x = x + 2) and then move on past the end of if clause.
So we can test for x < 5 and x < 10 in this way.


Writing our code properly we get
Writing our code properly we get
Line 130: Line 134:
   }
   }


You can use more than one elseif, but it gets messy. If you have a number of tests then it is better to test for each case individually. Easier to understand and much less chance of an error. Our above example would become
You can use more than one elseif, but it gets messy. If you have a number of tests then it is better to test for each case individually.
Easier to understand and much less chance of an error. Our above example would become
   if (x < 5) {
   if (x < 5) {
     x = x + 2
     x = x + 2
Line 164: Line 169:
To use a property you need its value. The best way to find out the path to a property is with Debug - Browse Internal Proprties.
To use a property you need its value. The best way to find out the path to a property is with Debug - Browse Internal Proprties.


Let us say we want to the current value of elevator-trim. From the menu select Debug and then Browse Internal Properties. Use the scroll-bar to go up and down the list and look at the options. One of them is controls. This is a good place to start, the elevator-trim is a control. Click on controls and inspect the new list of options.
Let us say we want to the current value of elevator-trim. From the menu select Debug and then Browse Internal Properties.
Use the scroll-bar to go up and down the list and look at the options. One of them is controls. This is a good place to start,
the elevator-trim is a control. Click on controls and inspect the new list of options.


One of them is flight. Good choice, the elevator-trim controls how the aircraft flies. Click on flight. Look at the list of variables displayed.
One of them is flight. Good choice, the elevator-trim controls how the aircraft flies. Click on flight.
Look at the list of variables displayed.


You will see elevator-trim = '0' (double) (It might not say 0.) The (double) means that it is a double-precision floating point number. This means that it can change in small amounts and has a decimal point with numbers after the decimal point. Make a note that it is a floating point number.
You will see elevator-trim = '0' (double) (It might not say 0.) The (double) means that it is a double-precision floating point number.
This means that it can change in small amounts and has a decimal point with numbers after the decimal point.
Make a note that it is a floating point number.


Look at the top of the dialog-box and you will see that it says /controls/flight. We can see that the variable is elevator-trim, so make a note that the path to the variable is /controls/flight/elevator-trim.
Look at the top of the dialog-box and you will see that it says /controls/flight. We can see that the variable is elevator-trim,
so make a note that the path to the variable is /controls/flight/elevator-trim.


You can close the dialog-box.
You can close the dialog-box.
Line 177: Line 188:
   getProp("/controls/flight/elevator-trim")
   getProp("/controls/flight/elevator-trim")


Having got the current value we probably want to change it. To do that we use setProp. Lets pretend that the current value is 0.175 and we want to make it 0.200. We use
Having got the current value we probably want to change it. To do that we use setProp. Lets pretend that the current value is 0.175
and we want to make it 0.200. We use
   setProp("/controls/flight/elevator-trim", 0.200)
   setProp("/controls/flight/elevator-trim", 0.200)


Elevator trim is a double (floating point) number. The range of values will be -1.000 through 0 to +1.000.
Elevator trim is a double (floating point) number. The range of values will be -1.000 through 0 to +1.000.


If the value is an integer (int) the range of values is ... -3, -2, -1, 0, 1, +2, +3 ... This doesn't mean that -3 is a suitable value for that specific property, it just means that you can pass -3 as a value without crashing the system.
If the value is an integer (int) the range of values is ... -3, -2, -1, 0, 1, +2, +3 ... This doesn't mean that -3 is a suitable value
for that specific property, it just means that you can pass -3 as a value without crashing the system.


Sometimes the value is a boolen (bool). This means that it is either true or false. Then you would use
Sometimes the value is a boolen (bool). This means that it is either true or false. Then you would use
Line 190: Line 203:
You can also use 1 instead of "true" and 0 instead of "false". If you use getProp, you will get 0 and 1 as your value, not "true" and "false."
You can also use 1 instead of "true" and 0 instead of "false". If you use getProp, you will get 0 and 1 as your value, not "true" and "false."


In multi-engined aircraft you can use throttleAxis() when you are adjusting the throttle with an axis. This will do all engines. But if you are using a button you need to set the throttle for all engines at the same time. To do this you need props.setAll(). It is a waste of time to try to take the throttles past maximum, so you first get the throttle setting, check if it is less than maximum, and if it is, increase it a bit. You end up with
In multi-engined aircraft you can use throttleAxis() when you are adjusting the throttle with an axis. This will do all engines.
But if you are using a button you need to set the throttle for all engines at the same time. To do this you need props.setAll().
It is a waste of time to try to take the throttles past maximum, so you first get the throttle setting, check if it is less than maximum,
and if it is, increase it a bit. You end up with
   <![CDATA[
   <![CDATA[
     if(getprop("controls/engines/engine/throttle") < 1 ) {
     if(getprop("controls/engines/engine/throttle") < 1 ) {
Line 214: Line 230:
If you are happy with a 1 second display, you can leave out the Time-to-display (and the comma before it.
If you are happy with a 1 second display, you can leave out the Time-to-display (and the comma before it.


The String-to-display can get hairy. To start off, choose one of your buttons (not the hat.) Let's say it is button number 3. Just before </script> add this line:
The String-to-display can get hairy. To start off, choose one of your buttons (not the hat.) Let's say it is button number 3.
Just before </script> add this line:
   gui.popupTip(sprintf("Button 3 pressed"),3)
   gui.popupTip(sprintf("Button 3 pressed"),3)
Don't forget to add a ; at the end of the previous line.
Don't forget to add a ; at the end of the previous line.
Line 222: Line 239:
Delete the line and the ; from your xml file.
Delete the line and the ; from your xml file.


This was not very useful in itself. What we normally want to display is some property. A good mexample is when adjusting a trim with a button - you have no idea where you are. You can use the HUD, but when you are transitioning to straight and level flight, it is much easier to remember a number from the last time, than the position of the trim on the HUD.
This was not very useful in itself. What we normally want to display is some property. A good example is when adjusting a trim
with a button - you have no idea where you are. You can use the HUD, but when you are transitioning to straight and level flight,
it is much easier to remember a number from the last time, than the position of the trim on the HUD.


We are going to display the value of elevator-trim. See getProp, setProp and setAll above to learn how to get the current value.
We are going to display the value of elevator-trim. See getProp, setProp and setAll above to learn how to get the current value.
Line 229: Line 248:
   getProp("/controls/flight/elevator-trim")
   getProp("/controls/flight/elevator-trim")


Now we want to display it. For a start we will have "Elevator-trim: " followed by the value that we got. But it is a number so we need to tell sprintf that there is a number coming, so we change our string to "Elevator-trim: %". We still need to tell sprintf that it is a floating point number, so we use "Elevator-trim: %f". But we would like it accurate to 3 decimal places, so we use "Elevator-trim" %.3f". Now we will have "Elevator-trim: %.3f", getProp("/controls/flight/elevator-trim").
Now we want to display it. For a start we will have "Elevator-trim: " followed by the value that we got. But it is a number,
so we need to tell sprintf that there is a number coming, so we change our string to "Elevator-trim: %".
We still need to tell sprintf that it is a floating point number, so we use "Elevator-trim: %f". But we would like it accurate
to 3 decimal places, so we use "Elevator-trim" %.3f". Now we will have "Elevator-trim: %.3f", getProp("/controls/flight/elevator-trim").


The line of code ends up as
The line of code ends up as
Line 238: Line 260:
Add the line to aileron-trim and rudder-trim (if you have it), not forgetting to change all occurrences of elevator to aileron and rudder.
Add the line to aileron-trim and rudder-trim (if you have it), not forgetting to change all occurrences of elevator to aileron and rudder.


We can make the display for elevator-trim a bit better. The elevator-trim control is usually a largish wheel that you turn. In the C172 it has a range of 9 turns. -4.5 to +4.5. Let's adjust our code to be similar. Our getProp returns -1.0 to +1.0, so if we multiply it by 4.5 we will get -4.5 to + 4.5. We will only need 2 decimal places, so the code becomes
We can make the display for elevator-trim a bit better. The elevator-trim control is usually a largish wheel that you turn.
In the C172 it has a range of 9 turns. -4.5 to +4.5. Let's adjust our code to be similar. Our getProp returns -1.0 to +1.0,
so if we multiply it by 4.5 we will get -4.5 to + 4.5. We will only need 2 decimal places, so the code becomes
   gui.popupTip(sprintf("Elevator-trim: %.2f", 4.5 * getprop("/controls/flight/elevator-trim")))
   gui.popupTip(sprintf("Elevator-trim: %.2f", 4.5 * getprop("/controls/flight/elevator-trim")))


Line 254: Line 278:
   interpolate(property-to-adjust, target-value, time-to-get-there-in-seconds)
   interpolate(property-to-adjust, target-value, time-to-get-there-in-seconds)


An example of its use would be in using a non-repeatable button to adjust aileron-trim. You could make repetitive pushes of the button, but that is not satisfactory. Much easier to use interpolate. You want the aileron trim to go from center to max (1.0) in 15 seconds. the code is
An example of its use would be in using a non-repeatable button to adjust aileron-trim. You could make repetitive pushes of the button,
but that is not satisfactory. Much easier to use interpolate. You want the aileron trim to go from center to max (1.0) in 15 seconds. the code is
   interpolate("controls/flight/aileron-trim", 1, 15)
   interpolate("controls/flight/aileron-trim", 1, 15)
You give the button a tap and in 15 seconds time the aileron-trim is at 1.0.
You give the button a tap and in 15 seconds time the aileron-trim is at 1.0.


But that was starting at 0. If the trim is at 0.5 when you start, you want it to get to max in half the time, 7.5 seconds. The trick is to get the current aileron-trim, subtract it from the max, thus giving you the change still needed, and use that to factor the time-to-get-there. This gives you
But that was starting at 0. If the trim is at 0.5 when you start, you want it to get to max in half the time, 7.5 seconds.
The trick is to get the current aileron-trim, subtract it from the max, thus giving you the change still needed,
and use that to factor the time-to-get-there. This gives you
   interpolate("controls/flight/aileron-trim", 1, (1 - getProp("controls/flight/aileron-trim") * 15)
   interpolate("controls/flight/aileron-trim", 1, (1 - getProp("controls/flight/aileron-trim") * 15)




All good and well, but if we are really using a non-repeatable button to adjust aileron-trim, we want to be able to stop the adjustment when it gets to a suitable value. The secret is to use <mod-up> to stop the action. To stop the action we use interpolate again, but this time we set the target to the current value, and the time-to-get-there as 0.
All good and well, but if we are really using a non-repeatable button to adjust aileron-trim, we want to be able to stop the adjustment
when it gets to a suitable value. The secret is to use <mod-up> to stop the action. To stop the action we use interpolate again,
but this time we set the target to the current value, and the time-to-get-there as 0.
   <mod-up>
   <mod-up>
     interpolate("controls/flight/aileron-trim", getProp("controls/flight/aileron-trim"), 0)
     interpolate("controls/flight/aileron-trim", getProp("controls/flight/aileron-trim"), 0)
   </mod-up>
   </mod-up>
Now, when the button is pressed, interpolation starts. Just once, because it is a non-repeatable button. When we are happy with the aileron-trim we release the button and interpolation stops.
Now, when the button is pressed, interpolation starts. Just once, because it is a non-repeatable button.
When we are happy with the aileron-trim we release the button and interpolation stops.


Nice.
Nice.
Line 274: Line 304:
=== Variables ===
=== Variables ===


Lets say we want our buttons to behave in different ways, depending on whether the aircraft is on the ground, aircraft is in the air, aircraft is an helicopter. To do this we have a variable called mode, which has 3 values
Lets say we want our buttons to behave in different ways, depending on whether the aircraft is on the ground, aircraft is in the air,
aircraft is an helicopter. To do this we have a variable called mode, which has 3 values
   mode = 1 Aircraft on ground
   mode = 1 Aircraft on ground
   mode = 2 Aircraft in air
   mode = 2 Aircraft in air
Line 280: Line 311:
Now, each time a button is pressed, we get the value of mode and use if to decide which action the button must carry out.
Now, each time a button is pressed, we get the value of mode and use if to decide which action the button must carry out.


Of course, we need some way to set the value of mode, say one of the buttons. Non-repeatable. Each time the button is clicked mode goes up 1 in value. If it is 3, then clicking takes it round to 1 again.
Of course, we need some way to set the value of mode, say one of the buttons. Non-repeatable. Each time the button is clicked
mode goes up 1 in value. If it is 3, then clicking takes it round to 1 again.


There are two ways of defining variables.
There are two ways of defining variables.
224

edits

Navigation menu