1# #################################################################################### 2# #################################################################################### 3# Nasal script to handle drag robot, in case there is no other dragger 4# 5# #################################################################################### 6# Author: Klaus Kerner 7# Version: 2012-03-08 8# 9# #################################################################################### 10# Concepts: 11# 1. search for allready existing dragger in the property tree done 12# 2. if an dragger does not exist, create a new one done 13# 3. place dragger in front of glider done 14# 4. run the dragger up into the sky mostly done 15# 5. after releasing tow reset the dragger mostly done 16# 6. allow redefining presets done 17 18 19 20# #################################################################################### 21# ## new properties in the property tree 22# ai/models/dragger 23# ai/models/dragger/id 24# ai/models/dragger/callsign 25# ai/models/dragger/valid 26# ai/models/dragger/position/latitude-deg 27# ai/models/dragger/position/longitude-deg 28# ai/models/dragger/position/altitude-ft 29# ai/models/dragger/orientation/true-heading-deg 30# ai/models/dragger/orientation/pitch-deg 31# ai/models/dragger/orientation/roll-deg 32# ai/models/dragger/velocities/true-airspeed-kt 33# ai/models/dragger/velocities/vertical-speed-fps 34# models/model[id_model]/path 35# models/model[id_model]/longitude-deg-prop 36# models/model[id_model]/latitude-deg-prop 37# models/model[id_model]/elevation-ft-prop 38# models/model[id_model]/heading-deg-prop 39# sim/glider/dragger/flags/exist flag for existence of robot 40# sim/glider/dragger/flags/run flag for triggering operation 41# sim/glider/dragger/robot/id_AI 42# sim/glider/dragger/robot/id_model 43# sim/glider/dragger/robot/wp0lat_deg wp0 reference point for different legs 44# sim/glider/dragger/robot/wp0lon_deg 45# sim/glider/dragger/robot/wp0alt_m 46# sim/glider/dragger/robot/wp0head_deg 47# sim/glider/dragger/robot/exit_height_m exit height for stopping robot 48# sim/glider/dragger/robot/anchorlat_deg anchor for checking leg position 49# sim/glider/dragger/robot/anchorlon_deg 50# sim/glider/dragger/robot/anchoralt_m 51# sim/glider/dragger/robot/leg_type storing type of leg, 0 start, 52# 1 turn, 53# 2 straight 54# 3 end 55# sim/glider/dragger/robot/leg_distance_m target distance in straight leg 56# sim/glider/dragger/robot/leg_angle_deg target turn angle in turn leg 57# sim/glider/dragger/robot/turnside 1: right turn, 0: left turn 58# sim/glider/dragger/robot/leg_segment storing segment of leg0, 59# 0 tauten, 60# 1 acceleration 61# storing segment of leg1 62# 2 roll in 63# 3 keep roll angle 64# 4 roll out 65# sim/glider/dragger/conf/glob_min_speed_takeoff_mps 66# .../glob/glob_min_speed_takeoff_mps 67# sim/glider/dragger/conf/glob_max_speed_mps 68# .../glob/glob_max_speed_mps 69# sim/glider/dragger/conf/glob_max_speed_lift_mps 70# .../glob/glob_max_speed_lift_mps 71# sim/glider/dragger/conf/glob_max_speed_tauten_mps 72# .../glob/glob_max_speed_tauten_mps 73# sim/glider/dragger/conf/glob_min_acceleration_mpss 74# .../glob/glob_min_acceleration_mpss 75# sim/glider/dragger/conf/glob_max_acceleration_mpss 76# .../glob/glob_max_acceleration_mpss 77# sim/glider/dragger/conf/glob_max_roll_deg 78# .../glob/glob_max_roll_deg 79# sim/glider/dragger/conf/glob_max_rollrate_degs 80# .../glob/glob_max_rollrate_degs 81# sim/glider/dragger/conf/glob_max_turnrate_degs 82# .../glob/glob_max_turnrate_degs 83# sim/glider/dragger/conf/glob_max_lift_height_m 84# .../glob/glob_max_lift_height_m 85# sim/glider/dragger/conf/glob_max_tautendist_m 86# .../glob/glob_max_tautendist_m 87 88# ## used properties from the property tree 89# environment/wind-from-north-fps 90# environment/wind-from-east-fps 91# environment/wind-from-down-fps 92# orientation/heading-deg 93# sim/glider/dragger/hooked 94 95 96 97# #################################################################################### 98# global variables: 99var dragrobot_timeincrement_s = 0.; # timer increment 100 101 102 103# #################################################################################### 104# set drag roboter parameters to global values, if not properly defined by plane 105# setup-file 106# store global values or plane-specific values to prepare for reset option 107var initRobotAttributes = func { 108 # constants for describing dragger attributes, if not defined by plane setup-file 109 var glob_min_speed_takeoff_mps = 20; # min. speed for take-off of drag-robot 110 var glob_max_speed_mps = 36; # max. speed of drag-robot 111 var glob_max_speed_lift_mps = 3; # max. lift speed of drag-robot 112 var glob_max_speed_tauten_mps = 3; # max. speed to tauten the rope 113 var glob_min_acceleration_mpss = 0.5; # min. acceleration 114 var glob_max_acceleration_mpss = 3; # max. acceleration 115 var glob_max_roll_deg = 20; # max. roll angle 116 var glob_max_rollrate_degs = 5; # max. roll rate per second 117 var glob_max_turnrate_degs = 3; # max. turn rate per second 118 # at max roll angle 119 var glob_max_lift_height_m = 800; # max. lifht height over start point 120 var glob_max_tautendist_m = 50; # max. distance for tauten the rope 121 122 if ( getprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps") == nil ) { 123 setprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps", 124 glob_min_speed_takeoff_mps); 125 setprop("sim/glider/dragger/glob/glob_min_speed_takeoff_mps", 126 glob_min_speed_takeoff_mps); 127 } 128 else { 129 setprop("sim/glider/dragger/glob/glob_min_speed_takeoff_mps", 130 getprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps")); 131 } 132 133 if ( getprop("sim/glider/dragger/conf/glob_max_speed_mps") == nil ) { 134 setprop("sim/glider/dragger/conf/glob_max_speed_mps", 135 glob_max_speed_mps); 136 setprop("sim/glider/dragger/glob/glob_max_speed_mps", 137 glob_max_speed_mps); 138 } 139 else { 140 setprop("sim/glider/dragger/glob/glob_max_speed_mps", 141 getprop("sim/glider/dragger/conf/glob_max_speed_mps")); 142 } 143 144 if ( getprop("sim/glider/dragger/conf/glob_max_speed_lift_mps") == nil ) { 145 setprop("sim/glider/dragger/conf/glob_max_speed_lift_mps", 146 glob_max_speed_lift_mps); 147 setprop("sim/glider/dragger/glob/glob_max_speed_lift_mps", 148 glob_max_speed_lift_mps); 149 } 150 else { 151 setprop("sim/glider/dragger/glob/glob_max_speed_lift_mps", 152 getprop("sim/glider/dragger/conf/glob_max_speed_lift_mps")); 153 } 154 155 if ( getprop("sim/glider/dragger/conf/glob_max_speed_tauten_mps") == nil ) { 156 setprop("sim/glider/dragger/conf/glob_max_speed_tauten_mps", 157 glob_max_speed_tauten_mps); 158 setprop("sim/glider/dragger/glob/glob_max_speed_tauten_mps", 159 glob_max_speed_tauten_mps); 160 } 161 else { 162 setprop("sim/glider/dragger/glob/glob_max_speed_tauten_mps", 163 getprop("sim/glider/dragger/conf/glob_max_speed_tauten_mps")); 164 } 165 166 if ( getprop("sim/glider/dragger/conf/glob_min_acceleration_mpss") == nil ) { 167 setprop("sim/glider/dragger/conf/glob_min_acceleration_mpss", 168 glob_min_acceleration_mpss); 169 setprop("sim/glider/dragger/glob/glob_min_acceleration_mpss", 170 glob_min_acceleration_mpss); 171 } 172 else { 173 setprop("sim/glider/dragger/glob/glob_min_acceleration_mpss", 174 getprop("sim/glider/dragger/conf/glob_min_acceleration_mpss")); 175 } 176 177 if ( getprop("sim/glider/dragger/conf/glob_max_acceleration_mpss") == nil ) { 178 setprop("sim/glider/dragger/conf/glob_max_acceleration_mpss", 179 glob_max_acceleration_mpss); 180 setprop("sim/glider/dragger/glob/glob_max_acceleration_mpss", 181 glob_max_acceleration_mpss); 182 } 183 else { 184 setprop("sim/glider/dragger/glob/glob_max_acceleration_mpss", 185 getprop("sim/glider/dragger/conf/glob_max_acceleration_mpss")); 186 } 187 188 if ( getprop("sim/glider/dragger/conf/glob_max_roll_deg") == nil ) { 189 setprop("sim/glider/dragger/conf/glob_max_roll_deg", 190 glob_max_roll_deg); 191 setprop("sim/glider/dragger/glob/glob_max_roll_deg", 192 glob_max_roll_deg); 193 } 194 else { 195 setprop("sim/glider/dragger/glob/glob_max_roll_deg", 196 getprop("sim/glider/dragger/conf/glob_max_roll_deg")); 197 } 198 199 if ( getprop("sim/glider/dragger/conf/glob_max_rollrate_degs") == nil ) { 200 setprop("sim/glider/dragger/conf/glob_max_rollrate_degs", 201 glob_max_rollrate_degs); 202 setprop("sim/glider/dragger/glob/glob_max_rollrate_degs", 203 glob_max_rollrate_degs); 204 } 205 else { 206 setprop("sim/glider/dragger/glob/glob_max_rollrate_degs", 207 getprop("sim/glider/dragger/conf/glob_max_rollrate_degs")); 208 } 209 210 if ( getprop("sim/glider/dragger/conf/glob_max_turnrate_degs") == nil ) { 211 setprop("sim/glider/dragger/conf/glob_max_turnrate_degs", 212 glob_max_turnrate_degs); 213 setprop("sim/glider/dragger/glob/glob_max_turnrate_degs", 214 glob_max_turnrate_degs); 215 } 216 else { 217 setprop("sim/glider/dragger/glob/glob_max_turnrate_degs", 218 getprop("sim/glider/dragger/conf/glob_max_turnrate_degs")); 219 } 220 221 if ( getprop("sim/glider/dragger/conf/glob_max_lift_height_m") == nil ) { 222 setprop("sim/glider/dragger/conf/glob_max_lift_height_m", 223 glob_max_lift_height_m); 224 setprop("sim/glider/dragger/glob/glob_max_lift_height_m", 225 glob_max_lift_height_m); 226 } 227 else { 228 setprop("sim/glider/dragger/glob/glob_max_lift_height_m", 229 getprop("sim/glider/dragger/conf/glob_max_lift_height_m")); 230 } 231 232 if ( getprop("sim/glider/dragger/conf/glob_max_tautendist_m") == nil ) { 233 setprop("sim/glider/dragger/conf/glob_max_tautendist_m", 234 glob_max_tautendist_m); 235 setprop("sim/glider/dragger/glob/glob_max_tautendist_m", 236 glob_max_tautendist_m); 237 } 238 else { 239 setprop("sim/glider/dragger/glob/glob_max_tautendist_m", 240 getprop("sim/glider/dragger/conf/glob_max_tautendist_m")); 241 } 242} 243 244 245 246# #################################################################################### 247# re-initialize presets 248var resetRobotAttributes = func { 249 # reading all global variables in case they has been changed in the property tree 250 setprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps", 251 getprop("sim/glider/dragger/glob/glob_min_speed_takeoff_mps")); 252 setprop("sim/glider/dragger/conf/glob_max_speed_mps", 253 getprop("sim/glider/dragger/glob/glob_max_speed_mps")); 254 setprop("sim/glider/dragger/conf/glob_max_speed_lift_mps", 255 getprop("sim/glider/dragger/glob/glob_max_speed_lift_mps")); 256 setprop("sim/glider/dragger/conf/glob_max_speed_tauten_mps", 257 getprop("sim/glider/dragger/glob/glob_max_speed_tauten_mps")); 258 setprop("sim/glider/dragger/conf/glob_min_acceleration_mpss", 259 getprop("sim/glider/dragger/glob/glob_min_acceleration_mpss")); 260 setprop("sim/glider/dragger/conf/glob_max_acceleration_mpss", 261 getprop("sim/glider/dragger/glob/glob_max_acceleration_mpss")); 262 setprop("sim/glider/dragger/conf/glob_max_roll_deg", 263 getprop("sim/glider/dragger/glob/glob_max_roll_deg")); 264 setprop("sim/glider/dragger/conf/glob_max_rollrate_degs", 265 getprop("sim/glider/dragger/glob/glob_max_rollrate_degs")); 266 setprop("sim/glider/dragger/conf/glob_max_turnrate_degs", 267 getprop("sim/glider/dragger/glob/glob_max_turnrate_degs")); 268 setprop("sim/glider/dragger/conf/glob_max_lift_height_m", 269 getprop("sim/glider/dragger/glob/glob_max_lift_height_m")); 270 setprop("sim/glider/dragger/conf/glob_max_tautendist_m", 271 getprop("sim/glider/dragger/glob/glob_max_tautendist_m")); 272} 273 274 275 276# #################################################################################### 277# check for allready available dragger 278var checkDragger = func { 279 280 #local variables 281 var dragid = -1; # the allready used id 282 var aiobjects = {}; # vector to keep all ai objects 283 284 aiobjects = props.globals.getNode("ai/models", 1).getChildren(); # store AI objects 285 foreach ( var aimember; aiobjects ) { 286 # get data from aimember 287 if ( (var c = aimember.getNode("callsign")) != nil) { 288 var callsign = c.getValue(); 289 if ( callsign == "dragger" ) { 290 dragid = aimember.getNode("id").getValue(); 291 } 292 } 293 } 294 return(dragid); 295} 296 297 298 299# #################################################################################### 300# get the next free id of ai/models members 301var getFreeAIID = func { 302 303 #local variables 304 var aiid = 0; # for the next unsused id 305 var aiobjects = {}; # vector to keep all ai objects 306 307 aiobjects = props.globals.getNode("ai/models", 1).getChildren(); # store AI objects 308 foreach ( var aimember; aiobjects ) { 309 # get data from aimember 310 if ( (var c = aimember.getNode("id")) != nil) { 311 var id = c.getValue(); 312 if ( aiid <= id ) { 313 aiid = id +1; 314 } 315 } 316 } 317 318# dirty bug-fix for double-used IDs, assign a most probably never reached ID (9999) 319# hopefully this will change in the future with correct ID assignment as the 320# AI-system does, needs access to flightgear core functions 321# return(aiid); 322 return(9999); 323} 324 325 326 327# #################################################################################### 328# get the next free id of models/model members 329var getFreeModelID = func { 330 331 #local variables 332 var modelid = 0; # for the next unsused id 333 var modelobjects = {}; # vector to keep all model objects 334 335 modelobjects = props.globals.getNode("models", 1).getChildren(); # get model objects 336 foreach ( var member; modelobjects ) { 337 # get data from member 338 if ( (var c = member.getNode("id")) != nil) { 339 var id = c.getValue(); 340 if ( modelid <= id ) { 341 modelid = id +1; 342 } 343 } 344 } 345 return(modelid); 346} 347 348 349 350# #################################################################################### 351# create the drag robot in the ai property tree 352var createDragRobot = func { 353 # place drag roboter with a distance, that the tow is nearly tautened 354 var rope_length_m = getprop("/sim/glider/towing/conf/rope_length_m"); 355 var tauten_relative = getprop("/sim/glider/towing/conf/rope_x1"); 356### var install_distance_m = rope_length_m * (tauten_relative - 0.02); 357 var install_distance_m = rope_length_m - 2.; 358 359 # local variables 360 var ac_pos = geo.aircraft_position(); # get position of aircraft 361 var ac_hd = getprop("orientation/heading-deg"); # get heading of aircraft 362 var dip = ac_pos.apply_course_distance( ac_hd , install_distance_m ); 363 # initial dragger position, 364 # close to tauten-distance 365 var dipalt_m = geo.elevation(dip.lat(), dip.lon()); # height at dragger position 366 var glob_max_lift_height_m = 367 getprop("sim/glider/dragger/conf/glob_max_lift_height_m"); 368 369 # get the next free ai id and model id 370 var freeAIid = getFreeAIID(); 371 var freeModelid = getFreeModelID(); 372 373 374 var dragger_ai = props.globals.getNode("ai/models/dragger", 1); 375 var dragger_mod = props.globals.getNode("models", 1); 376 var dragger_sim = props.globals.getNode("sim/glider/dragger/robot", 1); 377 var dragger_flg = props.globals.getNode("sim/glider/dragger/flags", 1); 378 379 dragger_sim.getNode("id_AI", 1).setIntValue(freeAIid); 380 dragger_sim.getNode("id_model", 1).setIntValue(freeModelid); 381 dragger_sim.getNode("leg_type", 1).setIntValue(0); 382 dragger_sim.getNode("leg_distance_m", 1).setValue(2000); 383 dragger_sim.getNode("leg_angle_deg", 1).setValue(ac_hd); 384 dragger_sim.getNode("leg_segment", 1).setIntValue(0); 385 386 dragger_flg.getNode("exist", 1).setIntValue(1); 387 388 389 dragger_ai.getNode("id", 1).setIntValue(freeAIid); 390 dragger_ai.getNode("callsign", 1).setValue("dragger"); 391 dragger_ai.getNode("valid", 1).setBoolValue(1); 392 dragger_ai.getNode("position/latitude-deg", 1).setValue(dip.lat()); 393 dragger_ai.getNode("position/longitude-deg", 1).setValue(dip.lon()); 394 dragger_ai.getNode("position/altitude-ft", 1).setValue(dipalt_m * M2FT); 395 dragger_ai.getNode("orientation/true-heading-deg", 1).setValue(ac_hd); 396 dragger_ai.getNode("orientation/pitch-deg", 1).setValue(0); 397 dragger_ai.getNode("orientation/roll-deg", 1).setValue(0); 398 dragger_ai.getNode("velocities/true-airspeed-kt", 1).setValue(0); 399 dragger_ai.getNode("velocities/vertical-speed-fps", 1).setValue(0); 400 401 dragger_mod.model = dragger_mod.getChild("model", freeModelid, 1); 402 dragger_mod.model.getNode("path", 1).setValue("Aircraft/asw20/Models/Dragger/robot.xml"); 403 dragger_mod.model.getNode("longitude-deg-prop", 1).setValue( 404 "ai/models/dragger/position/longitude-deg"); 405 dragger_mod.model.getNode("latitude-deg-prop", 1).setValue( 406 "ai/models/dragger/position/latitude-deg"); 407 dragger_mod.model.getNode("elevation-ft-prop", 1).setValue( 408 "ai/models/dragger/position/altitude-ft"); 409 dragger_mod.model.getNode("heading-deg-prop", 1).setValue( 410 "ai/models/dragger/orientation/true-heading-deg"); 411 dragger_mod.model.getNode("roll-deg-prop", 1).setValue( 412 "ai/models/dragger/orientation/roll-deg"); 413 dragger_mod.model.getNode("load", 1).remove(); 414 415 416 #storing initial position for reseting after reaching escape height 417 setprop("sim/glider/dragger/robot/wp0lat_deg", dip.lat() ); 418 setprop("sim/glider/dragger/robot/wp0lon_deg", dip.lon() ); 419 setprop("sim/glider/dragger/robot/wp0alt_m", dipalt_m ); 420 setprop("sim/glider/dragger/robot/wp0head_deg", ac_hd ); 421 setprop("sim/glider/dragger/robot/exit_height_m", dip.alt() + glob_max_lift_height_m ); 422} 423 424 425 426# #################################################################################### 427# main function to initialize the drag roboter 428# used by key "D" or gui 429var setupDragRobot = func { 430 431 # look for allready existing ai object with callsign "dragger" 432 var existingdragid = checkDragger(); 433 if ( existingdragid > -1 ) { # dragger allready exists, we can exit 434 atc_msg(" existing dragger id: ", existingdragid); 435 } 436 else { # dragger does not exist, we have to work 437 # create a new ai object with callsign "dragger" 438 # set initial position 439 createDragRobot(); 440 dragger_msg(" I will lift you up into the sky."); 441 } 442} 443 444 445 446# #################################################################################### 447# dummy function to delete the drag roboter 448# used by gui and dragrobot.nas functions 449var removeDragRobot = func { 450 451 # look for allready existing ai object with callsign "dragger" 452 # will be filled in the next future 453 454 # in any case, first stop the dragger 455 setprop("sim/glider/dragger/flags/run", 0); 456 457 # next check for the dragger is still existent 458 # if yes, 459 # remove the dragger from the property tree ai/models 460 # remove the dragger from the property tree models/ 461 # remove the dragger working properties 462 # if no, 463 # do nothing 464 465 # local variables 466 var modelsNode = {}; 467 468 if ( getprop("/sim/glider/dragger/flags/exist") == 1 ) { # does the dragger exist? 469 # remove 3d model from scenery 470 # identification is /models/model[x] with x=id_model 471 var id_model = getprop("sim/glider/dragger/robot/id_model"); 472 modelsNode = "models/model[" ~ id_model ~ "]"; 473 props.globals.getNode(modelsNode).remove(); 474 props.globals.getNode("ai/models/dragger").remove(); 475 props.globals.getNode("sim/glider/dragger/robot").remove(); 476 atc_msg("dragger removed"); 477 setprop("/sim/glider/dragger/flags/exist", 0); 478 } 479 else { # do nothing 480 atc_msg("dragger does not exist"); 481 } 482 483} 484 485 486 487# #################################################################################### 488# run the drag robot for start leg 489var leg0DragRobot = func { 490 491 # ################################################################################## 492 # Strategy: 493 # set flag for start 494 # tauten the rope 495 # accelerate up to minimum lift speed 496 # switch to next leg 497 498 499 500 501 var initpos_geo = geo.Coord.new(); 502 var dragpos_geo = geo.Coord.new(); 503 var temppos_geo = geo.Coord.new(); 504 505 var oldspeed_mps = 0; 506 var oldlift_mps = 0; 507 var oldheading_deg = 0; 508 var newspeed_mps = 0; 509 var newlift_mps = 0; 510 var newliftdist_m = 0; 511 var newelevation_m = 0; 512 var distance_m = 0; 513 var leg_distance_m = 0; 514 var deltatime_s = 0; 515 var leg_angle_deg = 0; 516 var headwind_mps = 0; 517 518 519 var segment = getprop("sim/glider/dragger/robot/leg_segment"); 520 var glob_min_speed_takeoff_mps = 521 getprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps"); 522 var glob_max_speed_tauten_mps = 523 getprop("sim/glider/dragger/conf/glob_max_speed_tauten_mps"); 524 var glob_min_acceleration_mpss = 525 getprop("sim/glider/dragger/conf/glob_min_acceleration_mpss"); 526 var glob_max_acceleration_mpss = 527 getprop("sim/glider/dragger/conf/glob_max_acceleration_mpss"); 528 var glob_max_tautendist_m = 529 getprop("sim/glider/dragger/conf/glob_max_tautendist_m"); 530 531 532 if ( dragrobot_timeincrement_s == 0 ) { 533 deltatime_s = getprop("sim/time/delta-sec"); 534 } 535 else { 536 deltatime_s = dragrobot_timeincrement_s; 537 } 538 539 540 oldspeed_mps = getprop("ai/models/dragger/velocities/true-airspeed-kt") * KT2MPS; 541 oldheading_deg = getprop("ai/models/dragger/orientation/true-heading-deg"); 542 543 initpos_geo.set_latlon( getprop("sim/glider/dragger/robot/wp0lat_deg"), 544 getprop("sim/glider/dragger/robot/wp0lon_deg"), 545 getprop("sim/glider/dragger/robot/wp0alt_m") ); 546 dragpos_geo.set_latlon( getprop("ai/models/dragger/position/latitude-deg"), 547 getprop("ai/models/dragger/position/longitude-deg"), 548 getprop("ai/models/dragger/position/altitude-ft") * FT2M); 549 550 headwind_mps = aircraft.wind_speed_from(oldheading_deg) * KT2MPS; 551 552 553 # update properties like speed and position 554 if ( segment == 1 ) { # accelerate to min take-off speed 555 newspeed_mps = oldspeed_mps + glob_max_acceleration_mpss * deltatime_s; 556 distance_m = (oldspeed_mps - headwind_mps) * deltatime_s 557 + 0.5 * glob_max_acceleration_mpss * deltatime_s * deltatime_s ; 558 } 559 else { # segment 0, tauten rope 560 if ( ( oldspeed_mps - headwind_mps ) < glob_max_speed_tauten_mps ) { 561 if ( oldspeed_mps < headwind_mps ) { 562 oldspeed_mps = headwind_mps; 563 } 564 newspeed_mps = glob_min_acceleration_mpss * deltatime_s + oldspeed_mps; 565 distance_m = (oldspeed_mps - headwind_mps) * deltatime_s 566 + 0.5 * glob_min_acceleration_mpss * deltatime_s * deltatime_s ; 567 if ( distance_m < 0.01 ) { # keep robot locked until speed is high enough 568 distance_m = 0; 569 } 570 } 571 else { 572 newspeed_mps = oldspeed_mps; 573 distance_m = (oldspeed_mps - headwind_mps) * deltatime_s ; 574 } 575 if ( dragpos_geo.direct_distance_to(initpos_geo) > glob_max_tautendist_m ) { 576 setprop("sim/glider/dragger/robot/leg_segment", 1); 577 } 578 } 579 580 temppos_geo.set_latlon(dragpos_geo.lat(), dragpos_geo.lon()); 581 newelevation_m = geo.elevation( temppos_geo.lat(), temppos_geo.lon() ); 582 583 dragpos_geo.apply_course_distance( oldheading_deg , distance_m ); 584 dragpos_geo.set_alt(newelevation_m); 585 586 setprop("ai/models/dragger/position/latitude-deg", dragpos_geo.lat()); 587 setprop("ai/models/dragger/position/longitude-deg", dragpos_geo.lon()); 588 setprop("ai/models/dragger/position/altitude-ft", dragpos_geo.alt() * M2FT); 589 setprop("ai/models/dragger/velocities/true-airspeed-kt", newspeed_mps * MPS2KT); 590 591 592 # check for exit criteria 593 if ( oldspeed_mps > glob_min_speed_takeoff_mps ) { 594 # set anchor point 595 setprop("sim/glider/dragger/robot/anchorlat_deg", dragpos_geo.lat()); 596 setprop("sim/glider/dragger/robot/anchorlon_deg", dragpos_geo.lon()); 597 setprop("sim/glider/dragger/robot/anchoralt_m", dragpos_geo.alt()); 598 # set flags for next leg 599 setprop("sim/glider/dragger/robot/leg_type", 2); # next one is straight forward 600 # set next exit criteria for straight leg, 200m ... 400m 601 leg_distance_m = 200 + rand() * 200; 602 setprop("sim/glider/dragger/robot/leg_distance_m", leg_distance_m ); 603 dragger_msg("straight ahead"); 604 dragger_msg( leg_distance_m, "m"); 605 } 606} 607 608 609 610# #################################################################################### 611# run the drag robot for turns 612var leg1DragRobot = func { 613 # turns are described by the turn angle, so the delta angle from heading at initial 614 # position to heading from current position is the criteria for exit 615 616 617 var initpos_geo = geo.Coord.new(); 618 var dragpos_geo = geo.Coord.new(); 619 620 var oldspeed_mps = 0; 621 var oldlift_mps = 0; 622 var oldheading_deg = 0; 623 var oldroll_deg = 0; 624 var deltatime_s = 0; 625 var distance_m = 0; 626 var newspeed_mps = 0; 627 var newlift_mps = 0; 628 var newelevation_m = 0; 629 var newroll_deg = 0; 630 var newturn_deg = 0; 631 var newheading_deg = 0; 632 var wind_from_east_mps = 0; 633 var wind_from_nord_mps = 0; 634 var wind_from_down_mps = 0; 635 636 637 var segment = getprop("sim/glider/dragger/robot/leg_segment"); 638 var side = getprop("sim/glider/dragger/robot/turnside"); 639 var targetheading_deg = getprop("sim/glider/dragger/robot/leg_angle_deg"); 640 var glob_min_speed_takeoff_mps = 641 getprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps"); 642 var glob_max_speed_mps = 643 getprop("sim/glider/dragger/conf/glob_max_speed_mps"); 644 var glob_max_speed_lift_mps = 645 getprop("sim/glider/dragger/conf/glob_max_speed_lift_mps"); 646 var glob_max_acceleration_mpss = 647 getprop("sim/glider/dragger/conf/glob_max_acceleration_mpss"); 648 var glob_max_roll_deg = 649 getprop("sim/glider/dragger/conf/glob_max_roll_deg"); 650 var glob_max_rollrate_degs = 651 getprop("sim/glider/dragger/conf/glob_max_rollrate_degs"); 652 var glob_max_turnrate_degs = 653 getprop("sim/glider/dragger/conf/glob_max_turnrate_degs"); 654 655 656 if ( dragrobot_timeincrement_s == 0 ) { 657 deltatime_s = getprop("sim/time/delta-sec"); 658 } 659 else { 660 deltatime_s = dragrobot_timeincrement_s; 661 } 662 663 oldspeed_mps = getprop("ai/models/dragger/velocities/true-airspeed-kt") * KT2MPS; 664 oldlift_mps = getprop("ai/models/dragger/velocities/vertical-speed-fps") * FT2M; 665 oldheading_deg = getprop("ai/models/dragger/orientation/true-heading-deg"); 666 oldroll_deg = getprop("ai/models/dragger/orientation/roll-deg"); 667 wind_from_east_mps = getprop("environment/wind-from-east-fps") * FT2M; 668 wind_from_nord_mps = getprop("environment/wind-from-north-fps") * FT2M; 669 wind_from_down_mps = getprop("environment/wind-from-down-fps") * FT2M; 670 671 dragpos_geo.set_latlon( getprop("ai/models/dragger/position/latitude-deg"), 672 getprop("ai/models/dragger/position/longitude-deg"), 673 getprop("ai/models/dragger/position/altitude-ft") * FT2M); 674 675 # calculate current roll angle for turns 676 if ( side == 1 ) { # right turns 677 if ( segment == 2 ) { 678 if ( oldroll_deg < glob_max_roll_deg) { 679 # calculate new roll angle 680 newroll_deg = oldroll_deg + deltatime_s * glob_max_rollrate_degs; 681 } 682 else { 683 newroll_deg = oldroll_deg; 684 setprop("sim/glider/dragger/robot/leg_segment", 3); 685 } 686 } 687 688 if (segment == 3 ) { 689 newroll_deg = oldroll_deg; 690 # check for target turn 691 if ( (oldheading_deg > targetheading_deg) 692 and 693 (oldheading_deg <= (targetheading_deg+5)) ) { 694 # turn finished 695 setprop("sim/glider/dragger/robot/leg_segment", 4); 696 } 697 # if yes, change segment type 698 } 699 700 if ( segment == 4 ) { 701 if ( oldroll_deg > 0) { 702 # calculate new roll angle 703 newroll_deg = oldroll_deg - deltatime_s * glob_max_rollrate_degs; 704 } 705 else { # also exit criteria 706 newroll_deg = 0; 707 # set anchor point 708 setprop("sim/glider/dragger/robot/anchorlat_deg", dragpos_geo.lat()); 709 setprop("sim/glider/dragger/robot/anchorlon_deg", dragpos_geo.lon()); 710 setprop("sim/glider/dragger/robot/anchoralt_m", dragpos_geo.alt()); 711 # set next leg 712 setprop("sim/glider/dragger/robot/leg_segment", 2); 713 setprop("sim/glider/dragger/robot/leg_type", 2); 714 var length_m = 100; # first turn after 100m 715 setprop("sim/glider/dragger/robot/leg_distance_m", length_m); 716 dragger_msg("straight leg"); 717 dragger_msg( length_m, "m"); 718 } 719 } 720 } 721 else { # left turns 722 if ( segment == 2 ) { 723 if ( oldroll_deg > -glob_max_roll_deg) { 724 # calculate new roll angle 725 newroll_deg = oldroll_deg - deltatime_s * glob_max_rollrate_degs; 726 } 727 else { 728 newroll_deg = oldroll_deg; 729 setprop("sim/glider/dragger/robot/leg_segment", 3); 730 } 731 } 732 733 if (segment == 3 ) { 734 newroll_deg = oldroll_deg; 735 # check for target turn 736 if ( (oldheading_deg < targetheading_deg) 737 and 738 (oldheading_deg >= (targetheading_deg-5)) ) { 739 # turn finished 740 setprop("sim/glider/dragger/robot/leg_segment", 4); 741 } 742 # if yes, change segment type 743 } 744 745 if ( segment == 4 ) { 746 if ( oldroll_deg < 0) { 747 # calculate new roll angle 748 newroll_deg = oldroll_deg + deltatime_s * glob_max_rollrate_degs; 749 } 750 else { # also exit criteria 751 newroll_deg = 0; 752 # set anchor point 753 setprop("sim/glider/dragger/robot/anchorlat_deg", dragpos_geo.lat()); 754 setprop("sim/glider/dragger/robot/anchorlon_deg", dragpos_geo.lon()); 755 setprop("sim/glider/dragger/robot/anchoralt_m", dragpos_geo.alt()); 756 # set next leg 757 setprop("sim/glider/dragger/robot/leg_segment", 2); 758 setprop("sim/glider/dragger/robot/leg_type", 2); 759 var length_m = 100; # first turn after 100m 760 setprop("sim/glider/dragger/robot/leg_distance_m", length_m); 761 dragger_msg("straight leg"); 762 dragger_msg( length_m, "m"); 763 } 764 } 765 } 766 # calculate current speed 767 if ( oldspeed_mps >= glob_max_speed_mps) { 768 newspeed_mps = oldspeed_mps; 769 distance_m = oldspeed_mps * deltatime_s; 770 } 771 else { 772 newspeed_mps = oldspeed_mps + glob_max_acceleration_mpss * deltatime_s; 773 distance_m = oldspeed_mps * deltatime_s 774 + 0.5 * glob_max_acceleration_mpss * deltatime_s * deltatime_s; 775 } 776 777 # calculate current lift 778 newlift_mps = glob_max_speed_lift_mps * (oldspeed_mps - glob_min_speed_takeoff_mps) / 779 (glob_max_speed_mps - glob_min_speed_takeoff_mps); 780 newliftdist_m = (newlift_mps + wind_from_down_mps) * deltatime_s; 781 782 783 # calculate current turn rate based on roll angle 784 newturn_deg = glob_max_turnrate_degs * newroll_deg / glob_max_roll_deg * deltatime_s; 785 786 # calculate new heading based on turn rate 787 if ( (oldheading_deg + newturn_deg) > 360 ) { # if a rightturn exceeds 360 heading 788 newheading_deg = oldheading_deg + newturn_deg - 360; 789 } 790 else { 791 if ( (oldheading_deg + newturn_deg) < 0 ) { # if a leftturn exceeds 0 heading 792 newheading_deg = oldheading_deg + newturn_deg +360; 793 } 794 else { # for all other headings 795 newheading_deg = oldheading_deg + newturn_deg; 796 } 797 } 798 799 # calculate new position based on new heading and distance increment 800 dragpos_geo.apply_course_distance( newheading_deg , distance_m ); 801 dragpos_geo.apply_course_distance( 270.0 , wind_from_east_mps * deltatime_s ); 802 dragpos_geo.apply_course_distance( 180.0 , wind_from_nord_mps * deltatime_s ); 803 newelevation_m = dragpos_geo.alt() + newliftdist_m; 804 dragpos_geo.set_alt(newelevation_m); 805 806 807 setprop("ai/models/dragger/position/latitude-deg", dragpos_geo.lat()); 808 setprop("ai/models/dragger/position/longitude-deg", dragpos_geo.lon()); 809 setprop("ai/models/dragger/position/altitude-ft", dragpos_geo.alt() * M2FT); 810 setprop("ai/models/dragger/orientation/true-heading-deg", newheading_deg); 811 setprop("ai/models/dragger/orientation/roll-deg", newroll_deg); 812 setprop("ai/models/dragger/velocities/true-airspeed-kt", newspeed_mps * MPS2KT); 813 setprop("ai/models/dragger/velocities/vertical-speed-fps", newlift_mps * M2FT); 814} 815 816 817 818# #################################################################################### 819# run the drag robot for straight legs 820var leg2DragRobot = func { 821 # straight legs are described by the length, so the delta distance from initial 822 # position to current position is the criteria for exit 823 824 825 826 var initpos_geo = geo.Coord.new(); 827 var dragpos_geo = geo.Coord.new(); 828 829 var oldspeed_mps = 0; 830 var oldheading_deg = 0; 831 var newspeed_mps = 0; 832 var newlift_mps = 0; 833 var newliftdist_m = 0; 834 var newelevation_m = 0; 835 var distance_m = 0; 836 var leg_distance_m = 0; 837 var deltatime_s = 0; 838 var leg_angle_deg = 0; 839 var wind_from_east_mps = 0; 840 var wind_from_nord_mps = 0; 841 var wind_from_down_mps = 0; 842 843 var glob_min_speed_takeoff_mps = 844 getprop("sim/glider/dragger/conf/glob_min_speed_takeoff_mps"); 845 var glob_max_speed_mps = 846 getprop("sim/glider/dragger/conf/glob_max_speed_mps"); 847 var glob_max_speed_lift_mps = 848 getprop("sim/glider/dragger/conf/glob_max_speed_lift_mps"); 849 var glob_max_acceleration_mpss = 850 getprop("sim/glider/dragger/conf/glob_max_acceleration_mpss"); 851 852 853 if ( dragrobot_timeincrement_s == 0 ) { 854 deltatime_s = getprop("sim/time/delta-sec"); 855 } 856 else { 857 deltatime_s = dragrobot_timeincrement_s; 858 } 859 860 oldspeed_mps = getprop("ai/models/dragger/velocities/true-airspeed-kt") * KT2MPS; 861 oldheading_deg = getprop("ai/models/dragger/orientation/true-heading-deg"); 862 leg_distance_m = getprop("sim/glider/dragger/robot/leg_distance_m"); 863 wind_from_east_mps = getprop("environment/wind-from-east-fps") * FT2M; 864 wind_from_nord_mps = getprop("environment/wind-from-north-fps") * FT2M; 865 wind_from_down_mps = getprop("environment/wind-from-down-fps") * FT2M; 866 867 initpos_geo.set_latlon( getprop("sim/glider/dragger/robot/anchorlat_deg"), 868 getprop("sim/glider/dragger/robot/anchorlon_deg"), 869 getprop("sim/glider/dragger/robot/anchoralt_m") ); 870 dragpos_geo.set_latlon( getprop("ai/models/dragger/position/latitude-deg"), 871 getprop("ai/models/dragger/position/longitude-deg"), 872 getprop("ai/models/dragger/position/altitude-ft") * FT2M); 873 874 if ( oldspeed_mps >= glob_max_speed_mps) { 875 newspeed_mps = oldspeed_mps; 876 distance_m = oldspeed_mps * deltatime_s; 877 } 878 else { 879 newspeed_mps = oldspeed_mps + glob_max_acceleration_mpss * deltatime_s; 880 distance_m = oldspeed_mps * deltatime_s 881 + 0.5 * glob_max_acceleration_mpss * deltatime_s * deltatime_s; 882 } 883 884 newlift_mps = glob_max_speed_lift_mps * (oldspeed_mps - glob_min_speed_takeoff_mps) / 885 (glob_max_speed_mps - glob_min_speed_takeoff_mps); 886 newliftdist_m = (newlift_mps + wind_from_down_mps) * deltatime_s; 887 888 dragpos_geo.apply_course_distance( oldheading_deg , distance_m ); 889 dragpos_geo.apply_course_distance( 270.0 , wind_from_east_mps * deltatime_s ); 890 dragpos_geo.apply_course_distance( 180.0 , wind_from_nord_mps * deltatime_s ); 891 newelevation_m = dragpos_geo.alt() + newliftdist_m; 892 dragpos_geo.set_alt(newelevation_m); 893 894 setprop("ai/models/dragger/position/latitude-deg", dragpos_geo.lat()); 895 setprop("ai/models/dragger/position/longitude-deg", dragpos_geo.lon()); 896 setprop("ai/models/dragger/position/altitude-ft", dragpos_geo.alt() * M2FT); 897 setprop("ai/models/dragger/velocities/true-airspeed-kt", newspeed_mps * MPS2KT); 898 setprop("ai/models/dragger/velocities/vertical-speed-fps", newlift_mps * M2FT); 899 900 901 # exit criteria to next turn 902 if ( dragpos_geo.direct_distance_to(initpos_geo) > leg_distance_m ) { 903 var turn_deg = 30 + rand() * 240; # turn range from 30� to 270� 904 if ( (oldheading_deg + turn_deg) >= 360) { 905 leg_angle_deg = oldheading_deg + turn_deg - 360; 906 } 907 else { 908 leg_angle_deg = oldheading_deg + turn_deg; 909 } 910 setprop("sim/glider/dragger/robot/leg_angle_deg", leg_angle_deg); 911 var side = rand(); 912 if (side > 0.5) { 913 setprop("sim/glider/dragger/robot/turnside", 1); 914 dragger_msg("turn right"); 915 dragger_msg( turn_deg , "deg"); 916 } 917 else { 918 setprop("sim/glider/dragger/robot/turnside", 0); 919 dragger_msg("turn left"); 920 dragger_msg( turn_deg , "deg"); 921 } 922 setprop("sim/glider/dragger/robot/leg_type", 1); 923 setprop("sim/glider/dragger/robot/leg_segment", 2); 924 } 925 926 # exit criteria to final drop-down: max height reached 927 if ( dragpos_geo.alt() > getprop("sim/glider/dragger/robot/exit_height_m") ) { 928 dragger_msg(" we have reached max height, bye bye"); 929 setprop("sim/glider/dragger/robot/leg_type", 3); 930 setprop("sim/glider/dragger/robot/leg_segment", 2); 931 } 932} 933 934 935 936# #################################################################################### 937# run the drag robot for final leg 938var leg3DragRobot = func { 939 940 dragger_msg(" turn right, I turn left" ); 941 # unhook from dragger 942 releaseDragger(); # function from towing.nas 943 944 945 # stop loop for updating roboter 946 if ( getprop("sim/glider/dragger/flags/run") == 1 ) { 947 setprop("sim/glider/dragger/flags/run", 0); 948 } 949 950 951 # reseting all variables and position to initial values 952 setprop("ai/models/dragger/position/latitude-deg", 953 getprop("sim/glider/dragger/robot/wp0lat_deg") ); 954 setprop("ai/models/dragger/position/longitude-deg", 955 getprop("sim/glider/dragger/robot/wp0lon_deg") ); 956 setprop("ai/models/dragger/position/altitude-ft", 957 getprop("sim/glider/dragger/robot/wp0alt_m") * M2FT); 958 setprop("ai/models/dragger/orientation/true-heading-deg", 959 getprop("sim/glider/dragger/robot/wp0head_deg") ); 960 setprop("ai/models/dragger/orientation/roll-deg", 0); 961 setprop("ai/models/dragger/velocities/true-airspeed-kt", 0); 962 setprop("ai/models/dragger/velocities/vertical-speed-fps", 0); 963 setprop("sim/glider/dragger/robot/leg_type", 0); 964 setprop("sim/glider/dragger/robot/leg_segment", 0); 965 966} 967 968 969 970# #################################################################################### 971# function to switch the drag roboter on or off running 972# used by key "d" and gui 973var startDragRobot = func { 974 if ( getprop("sim/glider/dragger/flags/run" ) == 1) { 975 setprop("sim/glider/dragger/flags/run", 0); 976 print(" stop the drag robot"); 977 } 978 else { 979 print(" start the drag robot"); 980 setprop("sim/glider/dragger/flags/run", 1); 981 } 982} 983 984 985 986# #################################################################################### 987# triggered function to run the drag roboter 988var runDragRobot = func { 989 if ( getprop("sim/glider/dragger/flags/run" ) == 1) { 990 var leg = -1; 991 992 leg = getprop("sim/glider/dragger/robot/leg_type"); 993 994 if ( leg == 0 ) { 995 leg0DragRobot(); 996 } 997 998 if ( leg == 1 ) { 999 leg1DragRobot(); 1000 } 1001 1002 if ( leg == 2 ) { 1003 leg2DragRobot(); 1004 } 1005 1006 if ( leg == 3 ) { 1007 leg3DragRobot(); 1008 } 1009 1010 settimer(runDragRobot, dragrobot_timeincrement_s); 1011 } 1012} 1013 1014 1015 1016# #################################################################################### 1017var pulling = setlistener("sim/glider/dragger/flags/run", runDragRobot); 1018var initializing_dragrobot = setlistener("sim/signals/fdm-initialized", initRobotAttributes); 1019