100 lines
4.1 KiB
Plaintext
100 lines
4.1 KiB
Plaintext
# Road check and auto pilot by ValKmjolnir
|
|
use std.fg_env;
|
|
use std.math;
|
|
|
|
var props = fg_env.props;
|
|
var geodinfo = fg_env.geodinfo;
|
|
var maketimer = fg_env.maketimer;
|
|
var simulation = fg_env.simulation;
|
|
|
|
var dt=0.01;
|
|
var intergral=0;
|
|
var derivative=0;
|
|
var previous_error=0;
|
|
var position_change = func(position_val,value) {
|
|
if (position_val+value>180)
|
|
position_val += value-360;
|
|
else if (position_val+value<-180)
|
|
position_val += value+360;
|
|
else
|
|
position_val += value;
|
|
return position_val;
|
|
}
|
|
var road_check_func = func() {
|
|
|
|
var lat = props.getNode("/position/latitude-deg",1).getValue();
|
|
var lon = props.getNode("/position/longitude-deg",1).getValue();
|
|
var position_info = geodinfo(lat,lon);
|
|
var position_names = position_info[1].names;
|
|
|
|
if ((position_names[0]=="Freeway") or (position_names[0]=="Road")) {
|
|
var car_heading = 0;
|
|
var lat_change = 0;
|
|
var lon_change = 0;
|
|
var left_range = 0;
|
|
var right_range = 0;
|
|
|
|
for (var i=0;i>-0.00005;i-=0.000001) {
|
|
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
|
lat_change = math.sin(D2R*car_heading);
|
|
lon_change = -math.cos(D2R*car_heading);
|
|
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(D2R*car_heading);
|
|
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(D2R*car_heading);
|
|
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
|
var other_names = other_position_info[1].names;
|
|
if ((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
|
right_range += 1;
|
|
else
|
|
break;
|
|
}
|
|
for (var i=0;i<0.00005;i+=0.000001) {
|
|
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
|
lat_change = math.sin(D2R*car_heading);
|
|
lon_change = -math.cos(D2R*car_heading);
|
|
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(D2R*car_heading);
|
|
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(D2R*car_heading);
|
|
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
|
var other_names = other_position_info[1].names;
|
|
if ((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
|
left_range+=1;
|
|
else
|
|
break;
|
|
}
|
|
var error=right_range-left_range;
|
|
intergral+=error*dt;
|
|
derivative=(error-previous_error)/dt;
|
|
var (Kp,Ki,Kd)=(1/900,0.05,0.005);
|
|
# print("change p ",Kp*error*error,' i ',Ki*intergral,' d ',Kd*derivative);
|
|
if (error<0)
|
|
props.getNode("/", 1).setValue("/controls/flight/rudder",-Kp*error*error+Ki*intergral+Kd*derivative);
|
|
else if (error>0)
|
|
props.getNode("/", 1).setValue("/controls/flight/rudder",Kp*error*error+Ki*intergral+Kd*derivative);
|
|
else
|
|
props.getNode("/", 1).setValue("/controls/flight/rudder",0);
|
|
|
|
# for simulation test, in fg these three lines are deleted
|
|
println(" rudder :",props.getNode("/controls/flight/rudder",1).getValue());
|
|
println(" dt :",dt,'\tintergral :',intergral,'\tderivative :',derivative);
|
|
println(" prev-err :",previous_error,'\terror :',error);
|
|
|
|
previous_error=error;
|
|
}
|
|
};
|
|
|
|
var road_check_timer = maketimer(0.01,road_check_func);
|
|
var toggle_auto_pilot = func() {
|
|
if (!road_check_timer.isRunning) {
|
|
intergral=0;
|
|
road_check_timer.start();
|
|
props.getNode("/sim/messages/copilot",1).setValue('/',"ze dong sheng teaan see tong yee tse yung. Auto Sheng Teaan System Activated!");
|
|
} else {
|
|
road_check_timer.stop();
|
|
props.getNode("/sim/messages/copilot",1).setValue('/',"ze dong sheng teaan see tong yee guan bee. Auto Sheng Teaan System is off.");
|
|
}
|
|
}
|
|
|
|
# this is used to simulate the running process in fg
|
|
# when using in fg, delete these lines below
|
|
toggle_auto_pilot();
|
|
road_check_timer.restart(0.1);
|
|
simulation(); |