2020-05-01 10:44:44 +08:00
|
|
|
#//Followme EV steering system by Sidi Liang
|
|
|
|
#//Contact: sidi.liang@gmail.com
|
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
var cache = {
|
|
|
|
new: func return { parents:[cache] };
|
|
|
|
};
|
|
|
|
|
|
|
|
var memoize = { callback:nil };
|
|
|
|
|
|
|
|
memoize.new = func(code) {
|
|
|
|
return { parents:[memoize], callback:code, cache:cache.new() };
|
|
|
|
}
|
|
|
|
|
|
|
|
memoize._save = func(value) me.cache[value] = me.callback(value);
|
|
|
|
memoize.lookup = func(value) {
|
|
|
|
var found = me.cache[value];
|
|
|
|
if (found) {
|
|
|
|
#//print("cached:",found,"\n");
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
#//print("Calculated:", value);
|
|
|
|
return me._save(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
var Steering = {
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
new: func() {
|
|
|
|
print("Steering system initialized!");
|
2020-04-22 19:39:11 +08:00
|
|
|
var steering = { parents:[Steering] };
|
|
|
|
props.getNode("/controls/steering_wheel/steering_limit-deg", 1).setValue(steering.steeringLimit * R2D);
|
|
|
|
return steering;
|
2020-01-17 15:33:43 +08:00
|
|
|
},
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
mode: 0, #//0: direct; 1: advanced
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
debugMode: 0,
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
input: 0, #//-1: left, 1:right, 0: none
|
|
|
|
command: 0, #//Steering command, range from -1 to 1
|
2020-05-16 18:13:53 +08:00
|
|
|
commandNode: props.getNode("/controls/flight/rudder", 1),
|
2020-01-17 15:33:43 +08:00
|
|
|
steeringAngle: 0, #//in rad
|
2020-04-22 19:39:11 +08:00
|
|
|
#steeringAngleDeg: 0, #//in degrees
|
|
|
|
|
2021-08-16 12:58:56 +08:00
|
|
|
#//steeringLimit: 7.8539815, #// 2.5 * 3.1415926 = 7.8539815 5 * 3.1415926 = 15.707963 3.1415926 / 4 = 0.78359815
|
|
|
|
steeringLimit: 15.707963,
|
2020-04-22 19:39:11 +08:00
|
|
|
|
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
powPointThree: memoize.new( func(value){
|
|
|
|
return math.pow(value, 0.3);
|
|
|
|
}),
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
powPointOne: memoize.new( func(value){
|
|
|
|
return math.pow(value, 0.1);
|
|
|
|
}),
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
steeringStep:func(rad){
|
|
|
|
return 0.1 * me.powPointOne.lookup(sprintf("%.1f", math.abs(rad))) + 0.04;
|
|
|
|
},
|
|
|
|
neutralStep: func(rad){
|
|
|
|
var speed = props.getNode("/", 1).getValue("sim/multiplay/generic/float[15]");
|
2020-04-22 19:39:11 +08:00
|
|
|
return 0.03 * me.powPointThree.lookup(sprintf("%.1f", math.abs(speed))) * math.abs(rad);
|
2020-01-17 15:33:43 +08:00
|
|
|
},
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
mainLoop: func(){
|
|
|
|
if(me.input == 0)
|
|
|
|
{
|
|
|
|
if(math.abs(me.steeringAngle) <=0.2)
|
2020-01-17 20:30:27 +08:00
|
|
|
{
|
2020-01-17 15:33:43 +08:00
|
|
|
me.steeringAngle = 0;
|
2020-05-16 18:13:53 +08:00
|
|
|
me.command = me.steeringAngle / me.steeringLimit; #//The steering wheel could rotate for two circles and a half
|
|
|
|
me.commandNode.setValue(me.command);
|
2020-04-22 19:39:11 +08:00
|
|
|
#me.steeringAngleDeg = me.steeringAngle * R2D;
|
|
|
|
#props.getNode("/",1).setValue("/controls/steering_wheel", me.steeringAngleDeg);
|
2020-01-17 20:30:27 +08:00
|
|
|
}
|
2020-01-17 15:33:43 +08:00
|
|
|
if(me.steeringAngle == 0)
|
|
|
|
{
|
|
|
|
me.stopTimer();
|
|
|
|
return 0;
|
|
|
|
}
|
2020-01-17 20:29:25 +08:00
|
|
|
else if(me.steeringAngle >= 0.05)
|
2020-01-17 15:33:43 +08:00
|
|
|
me.steeringAngle -= me.neutralStep(me.steeringAngle);
|
2020-01-17 20:33:32 +08:00
|
|
|
else if(me.steeringAngle <= -0.05)
|
2020-01-17 15:33:43 +08:00
|
|
|
me.steeringAngle += me.neutralStep(me.steeringAngle);
|
|
|
|
}
|
|
|
|
else if(me.input == 1 and me.steeringAngle < me.steeringLimit)
|
|
|
|
{
|
|
|
|
if(me.steeringAngle < 0)
|
|
|
|
{
|
|
|
|
me.steeringAngle += me.neutralStep(me.steeringAngle);
|
|
|
|
me.steeringAngle += 0.35 * me.input;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
me.steeringAngle += me.steeringStep(me.steeringAngle);
|
|
|
|
}
|
|
|
|
else if(me.input == -1 and me.steeringAngle > (-me.steeringLimit))
|
|
|
|
{
|
|
|
|
if(me.steeringAngle > 0)
|
|
|
|
{
|
|
|
|
me.steeringAngle -= me.neutralStep(me.steeringAngle);
|
|
|
|
me.steeringAngle -= 0.35;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
me.steeringAngle -= me.steeringStep(me.steeringAngle);
|
|
|
|
}
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
me.command = me.steeringAngle / me.steeringLimit; #//The steering wheel could rotate for two circles and a half
|
2020-04-22 19:39:11 +08:00
|
|
|
#me.steeringAngleDeg = me.steeringAngle * R2D;
|
2020-05-16 18:13:53 +08:00
|
|
|
me.commandNode.setValue(me.command);
|
2020-04-22 19:39:11 +08:00
|
|
|
#props.getNode("/",1).setValue("/controls/steering_wheel", me.steeringAngleDeg);
|
2020-01-17 15:33:43 +08:00
|
|
|
if(me.debugMode)
|
|
|
|
{
|
|
|
|
print("Steering system command:" ~ me.command);
|
|
|
|
print("Steering system angle rad:" ~ me.steeringAngle);
|
|
|
|
print("Steering system angle degrees:" ~ me.steeringAngleDeg);
|
|
|
|
}
|
|
|
|
},
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
inputLeft: func(){
|
|
|
|
me.input = -1;
|
|
|
|
if(!me.mode){
|
2020-04-22 19:39:11 +08:00
|
|
|
me.command = -0.5;
|
2020-01-17 15:33:43 +08:00
|
|
|
props.getNode("/",1).setValue("/controls/flight/rudder", me.command);
|
2020-04-22 19:39:11 +08:00
|
|
|
#me.steeringAngleDeg = me.steeringLimit * me.command * R2D;
|
|
|
|
#props.getNode("/",1).setValue("/controls/steering_wheel", me.steeringAngleDeg);
|
2020-01-17 15:33:43 +08:00
|
|
|
}else if(me.mode and !me.timerStarted){
|
|
|
|
me.startTimer();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
inputRight: func(){
|
|
|
|
me.input = 1;
|
|
|
|
if(!me.mode){
|
|
|
|
me.command = 0.5;
|
|
|
|
props.getNode("/",1).setValue("/controls/flight/rudder", me.command);
|
2020-04-22 19:39:11 +08:00
|
|
|
#me.steeringAngleDeg = me.steeringLimit * me.command * R2D;
|
|
|
|
#props.getNode("/",1).setValue("/controls/steering_wheel", me.steeringAngleDeg);
|
2020-01-17 15:33:43 +08:00
|
|
|
}else if(me.mode and !me.timerStarted){
|
|
|
|
me.startTimer();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
neutral: func(){
|
|
|
|
me.input = 0;
|
|
|
|
if(!me.mode){
|
|
|
|
me.command = 0;
|
|
|
|
props.getNode("/",1).setValue("/controls/flight/rudder", me.command);
|
2020-04-22 19:39:11 +08:00
|
|
|
#me.steeringAngleDeg = me.steeringLimit * me.command * R2D;
|
|
|
|
#props.getNode("/",1).setValue("/controls/steering_wheel", me.steeringAngleDeg);
|
2020-01-17 15:33:43 +08:00
|
|
|
}else if(me.mode and !me.timerStarted){
|
|
|
|
me.startTimer();
|
|
|
|
}
|
|
|
|
},
|
2020-04-22 19:39:11 +08:00
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
steeringTimer: nil,
|
|
|
|
timerCreated: 0,
|
|
|
|
timerStarted: 0,
|
|
|
|
startTimer: func(){
|
|
|
|
if(!me.timerCreated){
|
|
|
|
me.steeringTimer = maketimer(0.01, func me.mainLoop());
|
|
|
|
me.timerCreated = 1;
|
|
|
|
me.steeringTimer.simulatedTime = 1;
|
|
|
|
if(me.debugMode) print("Steering system timer created!");
|
|
|
|
}
|
|
|
|
me.steeringTimer.start();
|
|
|
|
me.timerStarted = 1;
|
|
|
|
if(me.debugMode) print("Steering system timer started!");
|
|
|
|
},
|
|
|
|
stopTimer: func(){
|
|
|
|
me.steeringTimer.stop();
|
|
|
|
me.timerStarted = 0;
|
|
|
|
if(me.debugMode) print("Steering system timer stopped!");
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-07-29 13:21:39 +08:00
|
|
|
#//Force calculation for front wheel drive(and four wheel drive)
|
|
|
|
var flForce = props.getNode("/fdm/jsbsim/external_reactions/FL");
|
|
|
|
var frForce = props.getNode("/fdm/jsbsim/external_reactions/FR");
|
|
|
|
var calculateFWForce = func(input){
|
|
|
|
var rad = input * 45 * D2R;
|
|
|
|
var x = math.cos(rad);
|
|
|
|
var y = math.sin(rad);
|
|
|
|
flForce.setValue("x", x);
|
|
|
|
flForce.setValue("y", y);
|
|
|
|
frForce.setValue("x", x);
|
|
|
|
frForce.setValue("y", y);
|
|
|
|
}
|
2020-01-17 15:33:43 +08:00
|
|
|
|
|
|
|
var steeringAssistance = Steering.new();
|
2020-07-29 13:21:39 +08:00
|
|
|
var frontWheelListener = setlistener("/controls/flight/rudder", func(n){ # create listener
|
|
|
|
calculateFWForce(n.getValue());
|
|
|
|
});
|
|
|
|
|
2020-01-17 15:33:43 +08:00
|
|
|
addcommand("enableAdvancedSteering", func() {
|
|
|
|
steeringAssistance.mode = 1;
|
|
|
|
print("Advanced Steering Enabled");
|
|
|
|
});
|
|
|
|
addcommand("disableAdvancedSteering", func() {
|
|
|
|
steeringAssistance.mode = 0;
|
|
|
|
print("Advanced Steering Disabled");
|
2020-04-22 19:39:11 +08:00
|
|
|
});
|
2021-08-16 12:58:56 +08:00
|
|
|
addcommand("setSteeringTravelToMin", func() {
|
|
|
|
steeringAssistance.steeringLimit = 0.78359815;
|
|
|
|
props.getNode("/controls/steering_wheel/steering_limit-deg", 1).setValue(steeringAssistance.steeringLimit * R2D);
|
|
|
|
print("Steering Travel Set To 1 : 1");
|
|
|
|
});
|
|
|
|
addcommand("setSteeringTravelToNormal", func() {
|
|
|
|
steeringAssistance.steeringLimit = 7.8539815;
|
|
|
|
props.getNode("/controls/steering_wheel/steering_limit-deg", 1).setValue(steeringAssistance.steeringLimit * R2D);
|
|
|
|
print("Steering Travel Set To Normal");
|
|
|
|
});
|
|
|
|
addcommand("setSteeringTravelToMax", func() {
|
|
|
|
steeringAssistance.steeringLimit = 15.707963;
|
|
|
|
props.getNode("/controls/steering_wheel/steering_limit-deg", 1).setValue(steeringAssistance.steeringLimit * R2D);
|
|
|
|
print("Steering Travel Set To Max");
|
|
|
|
});
|