1
0
Fork 0

Merged some of Alex's code changes.

Updates for better windows support in the Joystick module.
This commit is contained in:
curt 2000-07-20 04:16:59 +00:00
parent 3e98fcf671
commit 7a2ef1d57c
9 changed files with 451 additions and 400 deletions

View file

@ -103,7 +103,7 @@ void FGRadioStack::update( double lon, double lat, double elev ) {
nav1_loclat, nav1_loclon,
&az1, &az2, &s );
nav1_heading = az1;
// Alex: nav1_heading = az1 - FGBFI::getMagVar() / RAD_TO_DEG;
// Alex: nav1_heading = - (az1 - FGBFI::getMagVar() / RAD_TO_DEG);
// cout << " heading = " << nav1_heading
// << " dist = " << nav1_dist << endl;
@ -147,7 +147,7 @@ void FGRadioStack::update( double lon, double lat, double elev ) {
nav2_loclat, nav2_loclon,
&az1, &az2, &s );
nav2_heading = az1;
// Alex: nav2_heading = az1 - FGBFI::getMagVar() / RAD_TO_DEG;
// Alex: nav2_heading = - (az1 - FGBFI::getMagVar() / RAD_TO_DEG);
// cout << " heading = " << nav2_heading
// << " dist = " << nav2_dist << endl;

View file

@ -90,7 +90,7 @@ double FGSteam::get_TC_std () { _CatchUp(); return the_TC_std; }
////////////////////////////////////////////////////////////////////////
int FGSteam::_UpdatesPending = 999; /* Forces filter to reset */
int FGSteam::_UpdatesPending = 1000000; /* Forces filter to reset */
void FGSteam::update ( int timesteps )
@ -147,7 +147,7 @@ void FGSteam::_CatchUp()
just to be on the safe side. Doing it more than once will
waste CPU time but doesn't hurt anything really.
*/
if ( _UpdatesPending == 999 )
if ( _UpdatesPending > 999999 )
{ FGFeature::register_int ( "Avionics/NAV1/Localizer", &NAV1_LOC );
FGFeature::register_double ( "Avionics/NAV1/Latitude", &NAV1_Lat );
FGFeature::register_double ( "Avionics/NAV1/Longitude", &NAV1_Lon );
@ -321,10 +321,8 @@ void FGSteam::_CatchUp()
> have it tumble when you exceed the usual pitch or bank limits,
> put in those insidious turning errors ... for now anyway.
*/
// cout << "Updates pending = " << _UpdatesPending << endl;
if ( _UpdatesPending > 999 ) {
if ( _UpdatesPending > 999999 )
the_DG_err = FGBFI::getMagVar();
}
the_DG_degps = 0.0; /* HACK! */
if (dt<1.0) the_DG_err += dt * the_DG_degps;
the_DG_deg = FGBFI::getHeading () - the_DG_err;

View file

@ -32,7 +32,8 @@ FGControls::FGControls() :
aileron( 0.0 ),
elevator( 0.0 ),
elevator_trim( 1.969572E-03 ),
rudder( 0.0 )
rudder( 0.0 ),
throttle_idle( true )
{
for ( int engine = 0; engine < MAX_ENGINES; engine++ ) {
throttle[engine] = 0.0;
@ -46,11 +47,12 @@ FGControls::FGControls() :
void FGControls::reset_all()
{
controls.set_aileron(0.0);
controls.set_elevator(0.0);
controls.set_elevator_trim(0.0);
controls.set_rudder(0.0);
controls.set_throttle(FGControls::ALL_ENGINES, 0.0);
set_aileron(0.0);
set_elevator(0.0);
set_elevator_trim(0.0);
set_rudder(0.0);
set_throttle(FGControls::ALL_ENGINES, 0.0);
throttle_idle = true;
}

View file

@ -58,6 +58,7 @@ private:
double flaps;
double throttle[MAX_ENGINES];
double brake[MAX_WHEELS];
bool throttle_idle;
inline void CLAMP(double *x, double min, double max ) {
if ( *x < min ) { *x = min; }

View file

@ -85,10 +85,10 @@ int FGLaRCsim::update( int multiloop ) {
}
// copy control positions into the LaRCsim structure
Lat_control = controls.get_aileron();
Lat_control = controls.get_aileron() / current_options.get_speed_up();
Long_control = controls.get_elevator();
Long_trim = controls.get_elevator_trim();
Rudder_pedal = controls.get_rudder();
Rudder_pedal = controls.get_rudder() / current_options.get_speed_up();
Flap_handle = 30.0 * controls.get_flaps();
Throttle_pct = controls.get_throttle( 0 ) * 1.0;
Brake_pct[0] = controls.get_brake( 1 );

View file

@ -39,8 +39,12 @@
using std::string;
#ifdef WIN32
static const int MAX_JOYSTICKS = 2;
#else
static const int MAX_JOYSTICKS = 10;
static const int MAX_AXES = 10;
#endif
static const int MAX_AXES = _JS_MAX_AXES;
static const int MAX_BUTTONS = 10;
@ -48,16 +52,16 @@ static const int MAX_BUTTONS = 10;
* Property names for joysticks and axes.
*/
static const char * jsNames[] = {
"js0", "js1", "js2", "js3", "js4",
"js5", "js6", "js7", "js8", "js9"
"js0", "js1", "js2", "js3", "js4",
"js5", "js6", "js7", "js8", "js9"
};
static const char * axisNames[] = {
"axis0", "axis1", "axis2", "axis3", "axis4",
"axis5", "axis6", "axis7", "axis8", "axis9"
"axis0", "axis1", "axis2", "axis3", "axis4",
"axis5", "axis6", "axis7", "axis8", "axis9"
};
static const char * buttonNames[] = {
"button0", "button1", "button2", "button3", "button4",
"button5", "button6", "button7", "button8", "button9"
"button0", "button1", "button2", "button3", "button4",
"button5", "button6", "button7", "button8", "button9"
};
@ -65,13 +69,13 @@ static const char * buttonNames[] = {
* Settings for a single axis.
*/
struct axis {
axis () : value(0), offset(0.0), factor(1.0),
last_value(9999999), tolerance(0.002) {}
SGValue * value;
float offset;
float factor;
float last_value;
float tolerance;
axis () : value(0), offset(0.0), factor(1.0),
last_value(9999999), tolerance(0.002) {}
SGValue * value;
float offset;
float factor;
float last_value;
float tolerance;
};
@ -79,18 +83,18 @@ struct axis {
* Settings for a single button.
*/
struct button {
enum Action {
TOGGLE,
SWITCH,
ADJUST
};
button () : value(0), step(0.0), action(ADJUST), isRepeatable(true),
lastState(-1) {}
SGValue * value;
float step;
Action action;
bool isRepeatable;
int lastState;
enum Action {
TOGGLE,
SWITCH,
ADJUST
};
button () : value(0), step(0.0), action(ADJUST), isRepeatable(true),
lastState(-1) {}
SGValue * value;
float step;
Action action;
bool isRepeatable;
int lastState;
};
@ -98,10 +102,16 @@ struct button {
* Settings for a single joystick.
*/
struct joystick {
virtual ~joystick () { delete js; delete axes; }
jsJoystick * js;
axis * axes;
button * buttons;
virtual ~joystick () {
delete js;
delete axes;
delete buttons;
}
int naxes;
int nbuttons;
jsJoystick * js;
axis * axes;
button * buttons;
};
@ -117,91 +127,91 @@ static joystick joysticks[MAX_JOYSTICKS];
static void
setupDefaults ()
{
SGPropertyList &props = current_properties;
SGPropertyList &props = current_properties;
// Default axis 0 to aileron
if (!props.getValue("/input/js0/axis0/control")) {
props.setStringValue("/input/js0/axis0/control", "/controls/aileron");
props.setFloatValue("/input/js0/axis0/dead-band", 0.1);
}
// Default axis 0 to aileron
if (!props.getValue("/input/js0/axis0/control")) {
props.setStringValue("/input/js0/axis0/control", "/controls/aileron");
props.setFloatValue("/input/js0/axis0/dead-band", 0.1);
}
// Default axis 1 to elevator
if (!props.getValue("/input/js0/axis1/control")) {
props.setStringValue("/input/js0/axis1/control", "/controls/elevator");
props.setFloatValue("/input/js0/axis1/dead-band", 0.1);
props.setFloatValue("/input/js0/axis1/factor", -1.0);
}
// Default axis 1 to elevator
if (!props.getValue("/input/js0/axis1/control")) {
props.setStringValue("/input/js0/axis1/control", "/controls/elevator");
props.setFloatValue("/input/js0/axis1/dead-band", 0.1);
props.setFloatValue("/input/js0/axis1/factor", -1.0);
}
// Default axis 2 to throttle
// We need to fiddle with the offset
// and factor to make it work
if (!props.getValue("/input/js0/axis2/control")) {
props.setStringValue("/input/js0/axis2/control", "/controls/throttle");
props.setFloatValue("/input/js0/axis2/dead-band", 0.0);
props.setFloatValue("/input/js0/axis2/offset", -1.0);
props.setFloatValue("/input/js0/axis2/factor", -0.5);
}
// Default axis 2 to throttle
// We need to fiddle with the offset
// and factor to make it work
if (!props.getValue("/input/js0/axis2/control")) {
props.setStringValue("/input/js0/axis2/control", "/controls/throttle");
props.setFloatValue("/input/js0/axis2/dead-band", 0.0);
props.setFloatValue("/input/js0/axis2/offset", -1.0);
props.setFloatValue("/input/js0/axis2/factor", -0.5);
}
// Default axis 3 to rudder
if (!props.getValue("/input/js0/axis3/control")) {
props.setStringValue("/input/js0/axis3/control", "/controls/rudder");
props.setFloatValue("/input/js0/axis3/dead-band", 0.3);
}
// Default axis 3 to rudder
if (!props.getValue("/input/js0/axis3/control")) {
props.setStringValue("/input/js0/axis3/control", "/controls/rudder");
props.setFloatValue("/input/js0/axis3/dead-band", 0.3);
}
// Default button 0 to all brakes
if (!props.getValue("/input/js0/button0/control")) {
props.setStringValue("/input/js0/button0/action", "switch");
props.setStringValue("/input/js0/button0/control", "/controls/brake");
props.setFloatValue("/input/js0/button0/step", 1.0);
props.setFloatValue("/input/js0/button0/repeatable", false);
}
// Default button 0 to all brakes
if (!props.getValue("/input/js0/button0/control")) {
props.setStringValue("/input/js0/button0/action", "switch");
props.setStringValue("/input/js0/button0/control", "/controls/brake");
props.setFloatValue("/input/js0/button0/step", 1.0);
props.setFloatValue("/input/js0/button0/repeatable", false);
}
// Default button 1 to left brake.
if (!props.getValue("/input/js0/button1/control")) {
props.setStringValue("/input/js0/button1/action", "switch");
props.setStringValue("/input/js0/button1/control", "/controls/left-brake");
props.setFloatValue("/input/js0/button1/step", 1.0);
props.setFloatValue("/input/js0/button1/repeatable", false);
}
// Default button 1 to left brake.
if (!props.getValue("/input/js0/button1/control")) {
props.setStringValue("/input/js0/button1/action", "switch");
props.setStringValue("/input/js0/button1/control", "/controls/left-brake");
props.setFloatValue("/input/js0/button1/step", 1.0);
props.setFloatValue("/input/js0/button1/repeatable", false);
}
// Default button 2 to right brake.
if (!props.getValue("/input/js0/button2/control")) {
props.setStringValue("/input/js0/button2/action", "switch");
props.setStringValue("/input/js0/button2/control",
"/controls/right-brake");
props.setFloatValue("/input/js0/button2/step", 1.0);
props.setFloatValue("/input/js0/button2/repeatable", false);
}
// Default button 2 to right brake.
if (!props.getValue("/input/js0/button2/control")) {
props.setStringValue("/input/js0/button2/action", "switch");
props.setStringValue("/input/js0/button2/control",
"/controls/right-brake");
props.setFloatValue("/input/js0/button2/step", 1.0);
props.setFloatValue("/input/js0/button2/repeatable", false);
}
// Default buttons 3 and 4 to elevator trim
if (!props.getValue("/input/js0/button3/control")) {
props.setStringValue("/input/js0/button3/action", "adjust");
props.setStringValue("/input/js0/button3/control",
"/controls/elevator-trim");
props.setFloatValue("/input/js0/button3/step", 0.001);
props.setBoolValue("/input/js0/button3/repeatable", true);
}
if (!props.getValue("/input/js0/button4/control")) {
props.setStringValue("/input/js0/button4/action", "adjust");
props.setStringValue("/input/js0/button4/control",
"/controls/elevator-trim");
props.setFloatValue("/input/js0/button4/step", -0.001);
props.setBoolValue("/input/js0/button4/repeatable", true);
}
// Default buttons 3 and 4 to elevator trim
if (!props.getValue("/input/js0/button3/control")) {
props.setStringValue("/input/js0/button3/action", "adjust");
props.setStringValue("/input/js0/button3/control",
"/controls/elevator-trim");
props.setFloatValue("/input/js0/button3/step", 0.001);
props.setBoolValue("/input/js0/button3/repeatable", true);
}
if (!props.getValue("/input/js0/button4/control")) {
props.setStringValue("/input/js0/button4/action", "adjust");
props.setStringValue("/input/js0/button4/control",
"/controls/elevator-trim");
props.setFloatValue("/input/js0/button4/step", -0.001);
props.setBoolValue("/input/js0/button4/repeatable", true);
}
// Default buttons 5 and 6 to flaps
if (!props.getValue("/input/js0/button5/control")) {
props.setStringValue("/input/js0/button5/action", "adjust");
props.setStringValue("/input/js0/button5/control", "/controls/flaps");
props.setFloatValue("/input/js0/button5/step", -0.34);
props.setBoolValue("/input/js0/button5/repeatable", false);
}
if (!props.getValue("/input/js0/button6/control")) {
props.setStringValue("/input/js0/button6/action", "adjust");
props.setStringValue("/input/js0/button6/control", "/controls/flaps");
props.setFloatValue("/input/js0/button6/step", 0.34);
props.setBoolValue("/input/js0/button6/repeatable", false);
}
// Default buttons 5 and 6 to flaps
if (!props.getValue("/input/js0/button5/control")) {
props.setStringValue("/input/js0/button5/action", "adjust");
props.setStringValue("/input/js0/button5/control", "/controls/flaps");
props.setFloatValue("/input/js0/button5/step", -0.34);
props.setBoolValue("/input/js0/button5/repeatable", false);
}
if (!props.getValue("/input/js0/button6/control")) {
props.setStringValue("/input/js0/button6/action", "adjust");
props.setStringValue("/input/js0/button6/control", "/controls/flaps");
props.setFloatValue("/input/js0/button6/step", 0.34);
props.setBoolValue("/input/js0/button6/repeatable", false);
}
}
@ -211,209 +221,220 @@ setupDefaults ()
int
fgJoystickInit()
{
bool seen_joystick = false;
bool seen_joystick = false;
FG_LOG(FG_INPUT, FG_INFO, "Initializing joysticks");
FG_LOG(FG_INPUT, FG_INFO, "Initializing joysticks");
setupDefaults();
setupDefaults();
for (int i = 0; i < MAX_JOYSTICKS; i++) {
jsJoystick * js = new jsJoystick(i);
joysticks[i].js = js;
if (js->notWorking()) {
FG_LOG(FG_INPUT, FG_INFO, "Joystick " << i << " not found");
continue;
}
for (int i = 0; i < MAX_JOYSTICKS; i++) {
jsJoystick * js = new jsJoystick(i);
joysticks[i].js = js;
if (js->notWorking()) {
FG_LOG(FG_INPUT, FG_INFO, "Joystick " << i << " not found");
continue;
}
#ifdef WIN32
JOYCAPS jsCaps ;
joyGetDevCaps( i, &jsCaps, sizeof(jsCaps) );
int nbuttons = jsCaps.wNumButtons;
#else
int nbuttons = MAX_BUTTONS;
#endif
int naxes = js->getNumAxes();
joysticks[i].naxes = naxes;
joysticks[i].nbuttons = nbuttons;
FG_LOG(FG_INPUT, FG_INFO, "Initializing joystick " << i);
seen_joystick = true;
FG_LOG(FG_INPUT, FG_INFO, "Initializing joystick " << i);
seen_joystick = true;
// Set up range arrays
float minRange[js->getNumAxes()];
float maxRange[js->getNumAxes()];
float center[js->getNumAxes()];
// Set up range arrays
float minRange[naxes];
float maxRange[naxes];
float center[naxes];
// Initialize with default values
js->getMinRange(minRange);
js->getMaxRange(maxRange);
js->getCenter(center);
// Initialize with default values
js->getMinRange(minRange);
js->getMaxRange(maxRange);
js->getCenter(center);
// Allocate axes and buttons
joysticks[i].axes = new axis[js->getNumAxes()];
joysticks[i].buttons = new button[MAX_BUTTONS];
// Allocate axes and buttons
joysticks[i].axes = new axis[naxes];
joysticks[i].buttons = new button[nbuttons];
//
// Initialize the axes.
//
for (int j = 0; j < min(js->getNumAxes(), MAX_AXES); j++) {
axis &a = joysticks[i].axes[j];
//
// Initialize the axes.
//
for (int j = 0; j < naxes; j++) {
axis &a = joysticks[i].axes[j];
string base = "/input/";
base += jsNames[i];
base += '/';
base += axisNames[j];
FG_LOG(FG_INPUT, FG_INFO, " Axis " << j << ':');
string base = "/input/";
base += jsNames[i];
base += '/';
base += axisNames[j];
FG_LOG(FG_INPUT, FG_INFO, " Axis " << j << ':');
// Control property
string name = base;
name += "/control";
SGValue * value = current_properties.getValue(name);
if (value == 0) {
FG_LOG(FG_INPUT, FG_INFO, " no control defined");
continue;
}
const string &control = value->getStringValue();
a.value = current_properties.getValue(control, true);
FG_LOG(FG_INPUT, FG_INFO, " using control " << control);
// Control property
string name = base;
name += "/control";
SGValue * value = current_properties.getValue(name);
if (value == 0) {
FG_LOG(FG_INPUT, FG_INFO, " no control defined");
continue;
}
const string &control = value->getStringValue();
a.value = current_properties.getValue(control, true);
FG_LOG(FG_INPUT, FG_INFO, " using control " << control);
// Dead band
name = base;
name += "/dead-band";
value = current_properties.getValue(name);
if (value != 0)
js->setDeadBand(j, value->getFloatValue());
FG_LOG(FG_INPUT, FG_INFO, " dead-band is " << js->getDeadBand(j));
// Dead band
name = base;
name += "/dead-band";
value = current_properties.getValue(name);
if (value != 0)
js->setDeadBand(j, value->getFloatValue());
FG_LOG(FG_INPUT, FG_INFO, " dead-band is " << js->getDeadBand(j));
// Offset
name = base;
name += "/offset";
value = current_properties.getValue(name);
if (value != 0)
a.offset = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " offset is " << a.offset);
// Offset
name = base;
name += "/offset";
value = current_properties.getValue(name);
if (value != 0)
a.offset = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " offset is " << a.offset);
// Factor
name = base;
name += "/factor";
value = current_properties.getValue(name);
if (value != 0)
a.factor = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " factor is " << a.factor);
// Factor
name = base;
name += "/factor";
value = current_properties.getValue(name);
if (value != 0)
a.factor = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " factor is " << a.factor);
// Tolerance
name = base;
name += "/tolerance";
value = current_properties.getValue(name);
if (value != 0)
a.tolerance = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " tolerance is " << a.tolerance);
// Tolerance
name = base;
name += "/tolerance";
value = current_properties.getValue(name);
if (value != 0)
a.tolerance = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " tolerance is " << a.tolerance);
// Saturation
name = base;
name += "/saturation";
value = current_properties.getValue(name);
if (value != 0)
js->setSaturation(j, value->getFloatValue());
FG_LOG(FG_INPUT, FG_INFO, " saturation is " << js->getSaturation(j));
// Saturation
name = base;
name += "/saturation";
value = current_properties.getValue(name);
if (value != 0)
js->setSaturation(j, value->getFloatValue());
FG_LOG(FG_INPUT, FG_INFO, " saturation is " << js->getSaturation(j));
// Minimum range
name = base;
name += "/min-range";
value = current_properties.getValue(name);
if (value != 0)
minRange[j] = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " min-range is " << minRange[j]);
// Minimum range
name = base;
name += "/min-range";
value = current_properties.getValue(name);
if (value != 0)
minRange[j] = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " min-range is " << minRange[j]);
// Maximum range
name = base;
name += "/max-range";
value = current_properties.getValue(name);
if (value != 0)
maxRange[j] = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " max-range is " << maxRange[j]);
// Maximum range
name = base;
name += "/max-range";
value = current_properties.getValue(name);
if (value != 0)
maxRange[j] = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " max-range is " << maxRange[j]);
// Center
name = base;
name += "/center";
value = current_properties.getValue(name);
if (value != 0)
center[j] = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " center is " << center[j]);
}
// Center
name = base;
name += "/center";
value = current_properties.getValue(name);
if (value != 0)
center[j] = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " center is " << center[j]);
}
//
// Initialize the buttons.
//
for (int j = 0; j < MAX_BUTTONS; j++) {
button &b = joysticks[i].buttons[j];
//
// Initialize the buttons.
//
for (int j = 0; j < nbuttons; j++) {
button &b = joysticks[i].buttons[j];
string base = "/input/";
base += jsNames[i];
base += '/';
base += buttonNames[j];
FG_LOG(FG_INPUT, FG_INFO, " Button " << j << ':');
string base = "/input/";
base += jsNames[i];
base += '/';
base += buttonNames[j];
FG_LOG(FG_INPUT, FG_INFO, " Button " << j << ':');
// Control property
string name = base;
name += "/control";
cout << "Trying name " << name << endl;
SGValue * value = current_properties.getValue(name);
if (value == 0) {
FG_LOG(FG_INPUT, FG_INFO, " no control defined");
continue;
}
const string &control = value->getStringValue();
b.value = current_properties.getValue(control, true);
FG_LOG(FG_INPUT, FG_INFO, " using control " << control);
// Control property
string name = base;
name += "/control";
cout << "Trying name " << name << endl;
SGValue * value = current_properties.getValue(name);
if (value == 0) {
FG_LOG(FG_INPUT, FG_INFO, " no control defined");
continue;
}
const string &control = value->getStringValue();
b.value = current_properties.getValue(control, true);
FG_LOG(FG_INPUT, FG_INFO, " using control " << control);
// Step
name = base;
name += "/step";
value = current_properties.getValue(name);
if (value != 0)
b.step = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " step is " << b.step);
// Step
name = base;
name += "/step";
value = current_properties.getValue(name);
if (value != 0)
b.step = value->getFloatValue();
FG_LOG(FG_INPUT, FG_INFO, " step is " << b.step);
// Type
name = base;
name += "/action";
value = current_properties.getValue(name);
string action = "adjust";
if (value != 0)
action = value->getStringValue();
if (action == "toggle") {
b.action = button::TOGGLE;
b.isRepeatable = false;
} else if (action == "switch") {
b.action = button::SWITCH;
b.isRepeatable = false;
} else if (action == "adjust") {
b.action = button::ADJUST;
b.isRepeatable = true;
} else {
FG_LOG(FG_INPUT, FG_ALERT, " unknown action " << action);
action = "adjust";
b.action = button::ADJUST;
b.isRepeatable = true;
}
FG_LOG(FG_INPUT, FG_INFO, " action is " << action);
// Type
name = base;
name += "/action";
value = current_properties.getValue(name);
string action = "adjust";
if (value != 0)
action = value->getStringValue();
if (action == "toggle") {
b.action = button::TOGGLE;
b.isRepeatable = false;
} else if (action == "switch") {
b.action = button::SWITCH;
b.isRepeatable = false;
} else if (action == "adjust") {
b.action = button::ADJUST;
b.isRepeatable = true;
} else {
FG_LOG(FG_INPUT, FG_ALERT, " unknown action " << action);
action = "adjust";
b.action = button::ADJUST;
b.isRepeatable = true;
}
FG_LOG(FG_INPUT, FG_INFO, " action is " << action);
// Repeatability.
name = base;
name += "/repeatable";
value = current_properties.getValue(name);
if (value != 0)
b.isRepeatable = value->getBoolValue();
FG_LOG(FG_INPUT, FG_INFO, (b.isRepeatable ?
" repeatable" : " not repeatable"));
// Repeatability.
name = base;
name += "/repeatable";
value = current_properties.getValue(name);
if (value != 0)
b.isRepeatable = value->getBoolValue();
FG_LOG(FG_INPUT, FG_INFO, (b.isRepeatable ?
" repeatable" : " not repeatable"));
}
js->setMinRange(minRange);
js->setMaxRange(maxRange);
js->setCenter(center);
}
js->setMinRange(minRange);
js->setMaxRange(maxRange);
js->setCenter(center);
}
if (seen_joystick)
FG_LOG(FG_INPUT, FG_INFO, "Done initializing joysticks");
else
FG_LOG(FG_INPUT, FG_ALERT, "No joysticks detected");
if (seen_joystick)
FG_LOG(FG_INPUT, FG_INFO, "Done initializing joysticks");
else
FG_LOG(FG_INPUT, FG_ALERT, "No joysticks detected");
return seen_joystick;
return seen_joystick;
}
@ -423,112 +444,112 @@ fgJoystickInit()
int
fgJoystickRead()
{
int buttons;
int buttons;
for (int i = 0; i < MAX_JOYSTICKS; i++) {
jsJoystick * js = joysticks[i].js;
float axis_values[js->getNumAxes()];
if (js->notWorking()) {
continue;
}
js->read(&buttons, axis_values);
//
// Axes
//
for (int j = 0; j < min(MAX_AXES, js->getNumAxes()); j++) {
bool flag = true;
axis &a = joysticks[i].axes[j];
// If the axis hasn't changed, don't
// force the value.
if (fabs(axis_values[j] - a.last_value) <= a.tolerance)
continue;
else
a.last_value = axis_values[j];
if (a.value)
flag = a.value->setDoubleValue((axis_values[j] + a.offset) *
a.factor);
if (!flag)
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
<< i << ", axis " << j);
}
//
// Buttons
//
for (int j = 0; j < MAX_BUTTONS; j++) {
bool flag;
button &b = joysticks[i].buttons[j];
if (b.value == 0)
continue;
// Button is on.
if ((buttons & (1 << j)) > 0) {
// Repeating?
if (b.lastState == 1 && !b.isRepeatable)
continue;
switch (b.action) {
case button::TOGGLE:
if (b.step != 0.0) {
if (b.value->getDoubleValue() == 0.0)
flag = b.value->setDoubleValue(b.step);
else
flag = b.value->setDoubleValue(0.0);
} else {
if (b.value->getBoolValue())
flag = b.value->setBoolValue(false);
else
flag = b.value->setBoolValue(true);
}
break;
case button::SWITCH:
flag = b.value->setDoubleValue(b.step);
break;
case button::ADJUST:
if (!b.value->setDoubleValue(b.value->getDoubleValue() + b.step))
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
<< i << ", axis " << j);
break;
default:
flag = false;
break;
}
b.lastState = 1;
// Button is off
} else {
// Repeating?
if (b.lastState == 0 && !b.isRepeatable)
continue;
switch (b.action) {
case button::TOGGLE:
// no op
break;
case button::SWITCH:
flag = b.value->setDoubleValue(0.0);
break;
case button::ADJUST:
// no op
break;
default:
flag = false;
break;
for (int i = 0; i < MAX_JOYSTICKS; i++) {
jsJoystick * js = joysticks[i].js;
float axis_values[joysticks[i].naxes];
if (js->notWorking()) {
continue;
}
b.lastState = 0;
}
if (!flag)
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for "
<< jsNames[i] << ' ' << buttonNames[j]);
}
}
js->read(&buttons, axis_values);
return true;
//
// Axes
//
for (int j = 0; j < joysticks[i].naxes; j++) {
bool flag = true;
axis &a = joysticks[i].axes[j];
// If the axis hasn't changed, don't
// force the value.
if (fabs(axis_values[j] - a.last_value) <= a.tolerance)
continue;
else
a.last_value = axis_values[j];
if (a.value)
flag = a.value->setDoubleValue((axis_values[j] + a.offset) *
a.factor);
if (!flag)
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
<< i << ", axis " << j);
}
//
// Buttons
//
for (int j = 0; j < joysticks[i].nbuttons; j++) {
bool flag;
button &b = joysticks[i].buttons[j];
if (b.value == 0)
continue;
// Button is on.
if ((buttons & (1 << j)) > 0) {
// Repeating?
if (b.lastState == 1 && !b.isRepeatable)
continue;
switch (b.action) {
case button::TOGGLE:
if (b.step != 0.0) {
if (b.value->getDoubleValue() == 0.0)
flag = b.value->setDoubleValue(b.step);
else
flag = b.value->setDoubleValue(0.0);
} else {
if (b.value->getBoolValue())
flag = b.value->setBoolValue(false);
else
flag = b.value->setBoolValue(true);
}
break;
case button::SWITCH:
flag = b.value->setDoubleValue(b.step);
break;
case button::ADJUST:
if (!b.value->setDoubleValue(b.value->getDoubleValue() + b.step))
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick "
<< i << ", axis " << j);
break;
default:
flag = false;
break;
}
b.lastState = 1;
// Button is off
} else {
// Repeating?
if (b.lastState == 0 && !b.isRepeatable)
continue;
switch (b.action) {
case button::TOGGLE:
// no op
break;
case button::SWITCH:
flag = b.value->setDoubleValue(0.0);
break;
case button::ADJUST:
// no op
break;
default:
flag = false;
break;
}
b.lastState = 0;
}
if (!flag)
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for "
<< jsNames[i] << ' ' << buttonNames[j]);
}
}
return true;
}
// end of joystick.cxx

View file

@ -139,6 +139,10 @@ FGBFI::init ()
getThrottle, setThrottle);
current_properties.tieDouble("/controls/flaps",
getFlaps, setFlaps);
current_properties.tieBool ("/controls/flaps/raise",
0, setFlapsRaise);
current_properties.tieBool ("/controls/flaps/lower",
0, setFlapsLower);
current_properties.tieDouble("/controls/aileron",
getAileron, setAileron);
current_properties.tieDouble("/controls/rudder",
@ -779,6 +783,24 @@ FGBFI::setFlaps (double flaps)
}
void
FGBFI::setFlapsRaise (bool step)
{
if (step)
controls.set_flaps(controls.get_flaps() - 0.26);
printf ( "Raise: %i\n", step );
}
void
FGBFI::setFlapsLower (bool step)
{
if (step)
controls.set_flaps(controls.get_flaps() + 0.26);
printf ( "Lower: %i\n", step );
}
/**
* Get the aileron, from -1.0 (left) to 1.0 (right).
*/

View file

@ -116,6 +116,8 @@ public:
static void setThrottle (double throttle);
static void setFlaps (double flaps);
static void setFlapsRaise (bool step);
static void setFlapsLower (bool step);
static void setAileron (double aileron);
static void setRudder (double rudder);
static void setElevator (double elevator);

View file

@ -45,11 +45,14 @@ FGRAY::~FGRAY() {
}
// Ray Woodworth's motion chair has between 3 and 5 axes installed.
// Ray Woodworth (949) 262-9118 has a three axis motion chair.
//
// It expects +/- 5V signals for full scale. In channel order, axes are:
// roll, pitch, yaw, sway, surge, heave
// The drivers are capable of generating (in the same order)
// +/- 30deg, 30deg, 15deg, 12in, 12in, 12in
// +/- 30deg, 30deg, 30deg, 12in, 12in, 12in
// The signs of the motion are such that positive volts gives
// head right, head back, feet right, body right, body back, body up
//
// In this code implementation, the voltage outputs are generated
// using a ComputerBoards DDA06/Jr card and the associated Linux driver.
@ -62,7 +65,7 @@ bool FGRAY::gen_message() {
// cout << "generating RayWoodworth message" << endl;
FGInterface *f = cur_fdm_state;
int axis, subaxis;
const double fullscale[6] = { -0.8, -0.8, -0.25, /* radians */
const double fullscale[6] = { -0.5, -0.5, -0.5, /* radians */
-0.3, -0.3, -0.15 /* meters */ };
/* Figure out how big our timesteps are */
@ -99,10 +102,12 @@ bool FGRAY::gen_message() {
}
/* Make sure the angles are reasonable onscale */
while ( ang_pos < -M_PI ) {
/* We use an asymmetric mapping so that the chair behaves
reasonably when upside down. Otherwise it oscillates. */
while ( ang_pos < -2*M_PI/3 ) {
ang_pos += 2 * M_PI;
}
while ( ang_pos > M_PI ) {
while ( ang_pos > 4*M_PI/3 ) {
ang_pos -= 2 * M_PI;
}
@ -136,7 +141,7 @@ bool FGRAY::gen_message() {
ang_pos -= chair_heading;
/* Wash out the error at 5 sec timeconstant because
a standard rate turn is 3 deg/sec and the chair
can represent 15 degrees full scale. */
can just about represent 30 degrees full scale. */
chair_heading += ang_pos * dt * 0.2;
/* If they turn fast, at 90 deg error subtract 30 deg */
if ( fabs(ang_pos) > M_PI / 2 )