Subversion Repositories FlightCtrl

Rev

Rev 1586 | Rev 1588 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1586 Rev 1587
Line 1241... Line 1241...
1241
 if((EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG) && !(Looping_Roll || Looping_Nick))  // Höhenregelung
1241
 if((EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG) && !(Looping_Roll || Looping_Nick))  // Höhenregelung
1242
        {
1242
        {
1243
                #define HOOVER_GAS_AVERAGE 4096L                // 4096 * 2ms = 8.2s averaging
1243
                #define HOOVER_GAS_AVERAGE 4096L                // 4096 * 2ms = 8.2s averaging
1244
                #define HC_GAS_AVERAGE 4                        // 4 * 2ms= 8ms averaging
1244
                #define HC_GAS_AVERAGE 4                        // 4 * 2ms= 8ms averaging
1245
                #define OPA_OFFSET_STEP 10
1245
                #define OPA_OFFSET_STEP 10
1246
                int HCGas, HeightDeviation;
1246
                int HCGas, HeightDeviation = 0;
1247
                static int HeightTrimming = 0;  // rate for change of height setpoint
1247
                static int HeightTrimming = 0;  // rate for change of height setpoint
1248
                static int FilterHCGas = 0;
1248
                static int FilterHCGas = 0;
1249
                static int StickGasHoover = 120, HooverGas = 0, HooverGasMin = 0, HooverGasMax = 1023;
1249
                static int StickGasHover = 120, HoverGas = 0, HoverGasMin = 0, HoverGasMax = 1023;
1250
                static unsigned long HooverGasFilter = 0;
1250
                static unsigned long HoverGasFilter = 0;
1251
                static unsigned char delay = 100, BaroAtUpperLimit = 0, BaroAtLowerLimit = 0;
1251
                static unsigned char delay = 100, BaroAtUpperLimit = 0, BaroAtLowerLimit = 0;
1252
            int CosAttitude;    // for projection of hoover gas
1252
            int CosAttitude;    // for projection of hoover gas
Line 1253... Line 1253...
1253
 
1253
 
1254
                // get the current hooverpoint
1254
                // get the current hooverpoint
1255
                DebugOut.Analog[21] = HooverGas;
1255
                DebugOut.Analog[21] = HoverGas;
Line 1256... Line 1256...
1256
                DebugOut.Analog[18] = VarioMeter;
1256
                DebugOut.Analog[18] = VarioMeter;
1257
 
1257
 
1258
        // Expand the measurement
1258
        // Expand the measurement
Line 1356... Line 1356...
1356
                // PD-Control with respect to hoover point
1356
                // PD-Control with respect to hoover point
1357
                // the thrust loss out of horizontal attitude is compensated
1357
                // the thrust loss out of horizontal attitude is compensated
1358
                // the setpoint will be fine adjusted with the gas stick position
1358
                // the setpoint will be fine adjusted with the gas stick position
1359
                        if(FCFlags & FCFLAG_FLY) // trim setpoint only when flying
1359
                        if(FCFlags & FCFLAG_FLY) // trim setpoint only when flying
1360
                        {   // gas stick is above hoover point
1360
                        {   // gas stick is above hoover point
1361
                                if(StickGas > (StickGasHoover + HEIGHT_CONTROL_STICKTHRESHOLD) && !BaroAtUpperLimit)
1361
                                if(StickGas > (StickGasHover + HEIGHT_CONTROL_STICKTHRESHOLD) && !BaroAtUpperLimit)
1362
                                {
1362
                                {
1363
                                        if(HeightTrimmingFlag & HEIGHT_TRIM_DOWN)
1363
                                        if(HeightTrimmingFlag & HEIGHT_TRIM_DOWN)
1364
                                        {
1364
                                        {
1365
                                                HeightTrimmingFlag &= ~HEIGHT_TRIM_DOWN;
1365
                                                HeightTrimmingFlag &= ~HEIGHT_TRIM_DOWN;
1366
                                                SollHoehe = HoehenWert; // update setpoint to current heigth
1366
                                                SollHoehe = HoehenWert; // update setpoint to current heigth
1367
                                        }
1367
                                        }
1368
                                        HeightTrimmingFlag |= HEIGHT_TRIM_UP;
1368
                                        HeightTrimmingFlag |= HEIGHT_TRIM_UP;
1369
                                        HeightTrimming += abs(StickGas - (StickGasHoover + HEIGHT_CONTROL_STICKTHRESHOLD));
1369
                                        HeightTrimming += abs(StickGas - (StickGasHover + HEIGHT_CONTROL_STICKTHRESHOLD));
1370
                                } // gas stick is below hoover point
1370
                                } // gas stick is below hoover point
1371
                                else if(StickGas < (StickGasHoover - HEIGHT_CONTROL_STICKTHRESHOLD) && !BaroAtLowerLimit )
1371
                                else if(StickGas < (StickGasHover - HEIGHT_CONTROL_STICKTHRESHOLD) && !BaroAtLowerLimit )
1372
                                {
1372
                                {
1373
                                        if(HeightTrimmingFlag & HEIGHT_TRIM_UP)
1373
                                        if(HeightTrimmingFlag & HEIGHT_TRIM_UP)
1374
                                        {
1374
                                        {
1375
                                                HeightTrimmingFlag &= ~HEIGHT_TRIM_UP;
1375
                                                HeightTrimmingFlag &= ~HEIGHT_TRIM_UP;
1376
                                                SollHoehe = HoehenWert; // update setpoint to current heigth
1376
                                                SollHoehe = HoehenWert; // update setpoint to current heigth
1377
                                        }
1377
                                        }
1378
                                        HeightTrimmingFlag |= HEIGHT_TRIM_DOWN;
1378
                                        HeightTrimmingFlag |= HEIGHT_TRIM_DOWN;
1379
                                        HeightTrimming -= abs(StickGas - (StickGasHoover - HEIGHT_CONTROL_STICKTHRESHOLD));
1379
                                        HeightTrimming -= abs(StickGas - (StickGasHover - HEIGHT_CONTROL_STICKTHRESHOLD));
1380
                                }
1380
                                }
1381
                                else // Gas Stick in Hoover Range
1381
                                else // Gas Stick in Hover Range
1382
                                {
1382
                                {
1383
                                        if(HeightTrimmingFlag & (HEIGHT_TRIM_UP | HEIGHT_TRIM_DOWN))
1383
                                        if(HeightTrimmingFlag & (HEIGHT_TRIM_UP | HEIGHT_TRIM_DOWN))
1384
                                        {
1384
                                        {
1385
                                                HeightTrimmingFlag &= ~(HEIGHT_TRIM_UP | HEIGHT_TRIM_DOWN);
1385
                                                HeightTrimmingFlag &= ~(HEIGHT_TRIM_UP | HEIGHT_TRIM_DOWN);
1386
                                                HeightTrimming = 0;
1386
                                                HeightTrimming = 0;
Line 1391... Line 1391...
1391
                                // Trim height set point
1391
                                // Trim height set point
1392
                                if(abs(HeightTrimming) > 512)
1392
                                if(abs(HeightTrimming) > 512)
1393
                                {
1393
                                {
1394
                                        SollHoehe += (HeightTrimming * EE_Parameter.Hoehe_Verstaerkung)/(5 * 512 / 2); // move setpoint
1394
                                        SollHoehe += (HeightTrimming * EE_Parameter.Hoehe_Verstaerkung)/(5 * 512 / 2); // move setpoint
1395
                                        HeightTrimming = 0;
1395
                                        HeightTrimming = 0;
1396
                    LIMIT_MIN_MAX(SollHoehe, (HoehenWert-1024), (HoehenWert+1024)); // max. 10m Unterschied                             
1396
                    LIMIT_MIN_MAX(SollHoehe, (HoehenWert-1024), (HoehenWert+1024)); // max. 10m Unterschied
1397
                                        if(EE_Parameter.ExtraConfig & CFG2_VARIO_BEEP) beeptime = 75;
1397
                                        if(EE_Parameter.ExtraConfig & CFG2_VARIO_BEEP) beeptime = 75;
1398
                                        //update hoover gas stick value when setpoint is shifted
1398
                                        //update hoover gas stick value when setpoint is shifted
1399
                       if(!EE_Parameter.Hoehe_StickNeutralPoint)
1399
                       if(!EE_Parameter.Hoehe_StickNeutralPoint)
1400
                       {
1400
                       {
1401
                           StickGasHoover = HooverGas/STICK_GAIN; //rescale back to stick value
1401
                           StickGasHover = HoverGas/STICK_GAIN; //rescale back to stick value
1402
                           StickGasHoover = (StickGasHoover * UBat) / BattLowVoltageWarning;
1402
                           StickGasHover = (StickGasHover * UBat) / BattLowVoltageWarning;
1403
                           if(StickGasHoover < 70) StickGasHoover = 70;
1403
                           if(StickGasHover < 70) StickGasHover = 70;
1404
                           else if(StickGasHoover > 150) StickGasHoover = 150;
1404
                           else if(StickGasHover > 150) StickGasHover = 150;
1405
                       }
1405
                       }
1406
                                }
1406
                                }
1407
              if(BaroExpandActive) SollHoehe = HoehenWert; // update setpoint to current altitude if Expanding is active
1407
              if(BaroExpandActive) SollHoehe = HoehenWert; // update setpoint to current altitude if Expanding is active
1408
                        } //if FCFlags & MKFCFLAG_FLY
1408
                        } //if FCFlags & MKFCFLAG_FLY
1409
                        else
1409
                        else
1410
                        {
1410
                        {
1411
                         SollHoehe = HoehenWert - 400;
1411
                         SollHoehe = HoehenWert - 400;
1412
                         if(EE_Parameter.Hoehe_StickNeutralPoint) StickGasHoover = EE_Parameter.Hoehe_StickNeutralPoint;
1412
                         if(EE_Parameter.Hoehe_StickNeutralPoint) StickGasHover = EE_Parameter.Hoehe_StickNeutralPoint;
1413
                         else StickGasHoover = 120;
1413
                         else StickGasHover = 120;
1414
                         }
1414
                         }
1415
                        HCGas = HooverGas;      // take hoover gas (neutral point)
1415
                        HCGas = HoverGas;      // take hoover gas (neutral point)
1416
          }
1416
          }
1417
         if(HoehenWert > SollHoehe || !(EE_Parameter.ExtraConfig & CFG2_HEIGHT_LIMIT))
1417
         if(HoehenWert > SollHoehe || !(EE_Parameter.ExtraConfig & CFG2_HEIGHT_LIMIT))
1418
                 {
1418
                 {
1419
            // ------------------------- P-Part ----------------------------
1419
            // ------------------------- P-Part ----------------------------
1420
            tmp_long = (HoehenWert - SollHoehe); // positive when too high
1420
            tmp_long = (HoehenWert - SollHoehe); // positive when too high
1421
                        LIMIT_MIN_MAX(tmp_long, -2000, 2000);   // avoid overflov when casting to int
1421
                        LIMIT_MIN_MAX(tmp_long, -32767L, 32767L);       // avoid overflov when casting to int16_t
1422
                        HeightDeviation = (int)(tmp_long); // positive when too high
1422
                        HeightDeviation = (int)(tmp_long); // positive when too high
1423
                        tmp_int = (HeightDeviation * (long)Parameter_Hoehe_P) / 16; // p-part
1423
                        tmp_long = (tmp_long * (long)Parameter_Hoehe_P) / 16L; // p-part
-
 
1424
                        LIMIT_MIN_MAX(tmp_long, -255 * STICK_GAIN, 255 * STICK_GAIN); // more than 2 times the full range makes no sense
1424
                        HCGas -= tmp_int;
1425
                        HCGas -= tmp_long;
1425
                        // ------------------------- D-Part 1: Vario Meter ----------------------------
1426
                        // ------------------------- D-Part 1: Vario Meter ----------------------------
1426
                        tmp_int = VarioMeter / 8;
1427
                        tmp_long = VarioMeter / 8;
1427
                        if(tmp_int > 8) tmp_int = 8; // limit quadratic part on upward movement to avoid to much gas reduction
1428
                        if(tmp_long > 8) tmp_long = 8; // limit quadratic part on upward movement to avoid to much gas reduction
1428
                        if(tmp_int > 0) tmp_int = VarioMeter + (tmp_int * tmp_int) / 4;
1429
                        if(tmp_long > 0) tmp_long = VarioMeter + (tmp_long * tmp_long) / 4L;
1429
                        else            tmp_int = VarioMeter - (tmp_int * tmp_int) / 4;
1430
                        else             tmp_long = VarioMeter - (tmp_long * tmp_long) / 4L;
1430
                        tmp_int = (Parameter_Luftdruck_D * (long)(tmp_int)) / 128L; // scale to d-gain parameter
1431
                        tmp_long = (tmp_long * (long)Parameter_Luftdruck_D) / 128L; // scale to d-gain parameter
1431
                        LIMIT_MIN_MAX(tmp_int, -127, 255);
1432
                        LIMIT_MIN_MAX(tmp_long,-32 * STICK_GAIN, 64 * STICK_GAIN);
1432
                        HCGas -= tmp_int;
1433
                        HCGas -= tmp_long;
1433
                        // ------------------------ D-Part 2: ACC-Z Integral  ------------------------
1434
                        // ------------------------ D-Part 2: ACC-Z Integral  ------------------------
1434
                        tmp_int = ((Mess_Integral_Hoch / 128) * (long) Parameter_Hoehe_ACC_Wirkung) / (128 / STICK_GAIN);
1435
                        tmp_long = ((Mess_Integral_Hoch / 128L) * (int32_t) Parameter_Hoehe_ACC_Wirkung) / (128L / STICK_GAIN);
1435
                        LIMIT_MIN_MAX(tmp_int, -127, 255);
1436
                        LIMIT_MIN_MAX(tmp_long, -32 * STICK_GAIN, 64 * STICK_GAIN);
-
 
1437
                        HCGas -= tmp_long;
-
 
1438
 
-
 
1439
            if(BaroExpandActive) HCGas = HoverGas;
-
 
1440
                        // ------------------------ D-Part 3: GpsZ  ----------------------------------
-
 
1441
                        tmp_int = (Parameter_Hoehe_GPS_Z * (long)FromNaviCtrl_Value.GpsZ)/128L;
-
 
1442
            LIMIT_MIN_MAX(tmp_long, -32 * STICK_GAIN, 64 * STICK_GAIN);
1436
                        HCGas -= tmp_int;
1443
                        HCGas -= tmp_int;
-
 
1444
 
1437
                        // limit deviation from hoover point within the target region
1445
                        // limit deviation from hoover point within the target region
1438
                        if( (abs(HeightDeviation) < 150)  && (!HeightTrimming) && (HooverGas > 0)) // height setpoint is not changed and hoover gas not zero
1446
                        if( (abs(HeightDeviation) < 150)  && (!HeightTrimming) && (HoverGas > 0)) // height setpoint is not changed and hoover gas not zero
1439
                        {
1447
                        {
1440
                                LIMIT_MIN_MAX(HCGas, HooverGasMin, HooverGasMax); // limit gas around the hoover point
1448
                                LIMIT_MIN_MAX(HCGas, HoverGasMin, HoverGasMax); // limit gas around the hoover point
1441
                        }
1449
                        }
Line 1442... Line -...
1442
 
-
 
1443
            if(BaroExpandActive) HCGas = HooverGas;
-
 
1444
                        // ------------------------ D-Part 3: GpsZ  ----------------------------------
-
 
1445
                        tmp_int = (Parameter_Hoehe_GPS_Z * (long)FromNaviCtrl_Value.GpsZ)/128L;
-
 
1446
            LIMIT_MIN_MAX(tmp_int, -127, 255);
-
 
1447
                        HCGas -= tmp_int;
1450
 
1448
                        // strech control output by inverse attitude projection 1/cos
1451
                        // strech control output by inverse attitude projection 1/cos
1449
            // + 1/cos(angle)  ++++++++++++++++++++++++++
1452
            // + 1/cos(angle)  ++++++++++++++++++++++++++
1450
                        tmp_long2 = (int32_t)HCGas;
1453
                        tmp_long2 = (int32_t)HCGas;
1451
                        tmp_long2 *= 8192L;
1454
                        tmp_long2 *= 8192L;
Line 1455... Line 1458...
1455
                        FilterHCGas = (FilterHCGas * (HC_GAS_AVERAGE - 1) + HCGas) / HC_GAS_AVERAGE;
1458
                        FilterHCGas = (FilterHCGas * (HC_GAS_AVERAGE - 1) + HCGas) / HC_GAS_AVERAGE;
1456
                        // limit height control gas pd-control output
1459
                        // limit height control gas pd-control output
1457
                        LIMIT_MIN_MAX(FilterHCGas, EE_Parameter.Hoehe_MinGas * STICK_GAIN, (MAX_GAS - 20) * STICK_GAIN);
1460
                        LIMIT_MIN_MAX(FilterHCGas, EE_Parameter.Hoehe_MinGas * STICK_GAIN, (MAX_GAS - 20) * STICK_GAIN);
1458
                        // set GasMischanteil to HeightControlGasFilter
1461
                        // set GasMischanteil to HeightControlGasFilter
1459
            if(EE_Parameter.ExtraConfig & CFG2_HEIGHT_LIMIT)
1462
            if(EE_Parameter.ExtraConfig & CFG2_HEIGHT_LIMIT)
1460
                         {  // old version
1463
                        {  // old version
1461
                if(FilterHCGas > GasMischanteil) FilterHCGas = GasMischanteil; // nicht mehr als Gas
1464
                                LIMIT_MAX(FilterHCGas, GasMischanteil); // nicht mehr als Gas
1462
                         }
1465
                        }
1463
                        GasMischanteil = FilterHCGas;
1466
                        GasMischanteil = FilterHCGas;
1464
                  }
1467
                  }
1465
                }// EOF height control active
1468
                }// EOF height control active
1466
                else // HC not active
1469
                else // HC not active
1467
                {
1470
                {
1468
                        //update hoover gas stick value when HC is not active
1471
                        //update hoover gas stick value when HC is not active
1469
           if(!EE_Parameter.Hoehe_StickNeutralPoint)
1472
                        if(!EE_Parameter.Hoehe_StickNeutralPoint)
1470
                    {
1473
                        {
1471
                         StickGasHoover = HooverGas/STICK_GAIN; // rescale back to stick value
1474
                                StickGasHover = HoverGas/STICK_GAIN; // rescale back to stick value
1472
                         StickGasHoover = (StickGasHoover * UBat) / BattLowVoltageWarning;
1475
                                StickGasHover = (StickGasHover * UBat) / BattLowVoltageWarning;
1473
                        }
1476
                        }
1474
                        else StickGasHoover = EE_Parameter.Hoehe_StickNeutralPoint;
1477
                        else StickGasHover = EE_Parameter.Hoehe_StickNeutralPoint;
1475
            if(StickGasHoover < 70) StickGasHoover = 70;
-
 
1476
            else if(StickGasHoover > 150) StickGasHoover = 150;
1478
            LIMIT_MIN_MAX(StickGasHover, 70, 150); // reserve some range for trim up and down
1477
                        FilterHCGas = GasMischanteil;
1479
                        FilterHCGas = GasMischanteil;
1478
                }
1480
                }
Line 1479... Line 1481...
1479
 
1481
 
1480
                // Hoover gas estimation by averaging gas control output on small z-velocities
1482
                // Hover gas estimation by averaging gas control output on small z-velocities
1481
                // this is done only if height contol option is selected in global config and aircraft is flying
1483
                // this is done only if height contol option is selected in global config and aircraft is flying
1482
                if((FCFlags & FCFLAG_FLY) && !(FCFlags & FCFLAG_NOTLANDUNG))
1484
                if((FCFlags & FCFLAG_FLY) && !(FCFlags & FCFLAG_NOTLANDUNG))
1483
                {
1485
                {
1484
                        if(HooverGasFilter == 0)  HooverGasFilter = HOOVER_GAS_AVERAGE * (unsigned long)(GasMischanteil); // init estimation
1486
                        if(HoverGasFilter == 0)  HoverGasFilter = HOOVER_GAS_AVERAGE * (unsigned long)(GasMischanteil); // init estimation
1485
                        if(abs(VarioMeter) < 100) // only on small vertical speed
1487
                        if(abs(VarioMeter) < 100) // only on small vertical speed
1486
                        {
1488
                        {
1487
                                tmp_long2 = (int32_t)GasMischanteil; // take current thrust
1489
                                tmp_long2 = (int32_t)GasMischanteil; // take current thrust
1488
                                tmp_long2 *= CosAttitude;            // apply attitude projection
1490
                                tmp_long2 *= CosAttitude;            // apply attitude projection
Line 1489... Line 1491...
1489
                                tmp_long2 /= 8192;
1491
                                tmp_long2 /= 8192;
1490
 
1492
 
1491
                                // average vertical projected thrust
1493
                                // average vertical projected thrust
1492
                                if(modell_fliegt < 2000) // the first 4 seconds
1494
                                if(modell_fliegt < 2000) // the first 4 seconds
1493
                                {   // reduce the time constant of averaging by factor of 8 to get much faster a stable value
1495
                                {   // reduce the time constant of averaging by factor of 8 to get much faster a stable value
1494
                                        HooverGasFilter -= HooverGasFilter/(HOOVER_GAS_AVERAGE/8L);
1496
                                        HoverGasFilter -= HoverGasFilter/(HOOVER_GAS_AVERAGE/8L);
1495
                                        HooverGasFilter += 8L * tmp_long2;
1497
                                        HoverGasFilter += 8L * tmp_long2;
1496
                                }
1498
                                }
1497
                                else if(modell_fliegt < 4000) // the first 8 seconds
1499
                                else if(modell_fliegt < 4000) // the first 8 seconds
1498
                                {   // reduce the time constant of averaging by factor of 4 to get much faster a stable value
1500
                                {   // reduce the time constant of averaging by factor of 4 to get much faster a stable value
1499
                                        HooverGasFilter -= HooverGasFilter/(HOOVER_GAS_AVERAGE/4L);
1501
                                        HoverGasFilter -= HoverGasFilter/(HOOVER_GAS_AVERAGE/4L);
1500
                                        HooverGasFilter += 4L * tmp_long2;
1502
                                        HoverGasFilter += 4L * tmp_long2;
1501
                                }
1503
                                }
1502
                                else if(modell_fliegt < 8000) // the first 16 seconds
1504
                                else if(modell_fliegt < 8000) // the first 16 seconds
1503
                                {   // reduce the time constant of averaging by factor of 2 to get much faster a stable value
1505
                                {   // reduce the time constant of averaging by factor of 2 to get much faster a stable value
1504
                                        HooverGasFilter -= HooverGasFilter/(HOOVER_GAS_AVERAGE/2L);
1506
                                        HoverGasFilter -= HoverGasFilter/(HOOVER_GAS_AVERAGE/2L);
1505
                                        HooverGasFilter += 2L * tmp_long2;
1507
                                        HoverGasFilter += 2L * tmp_long2;
1506
                                }
1508
                                }
1507
                                else //later
1509
                                else //later
1508
                                {
1510
                                {
1509
                                        HooverGasFilter -= HooverGasFilter/HOOVER_GAS_AVERAGE;
1511
                                        HoverGasFilter -= HoverGasFilter/HOOVER_GAS_AVERAGE;
1510
                                        HooverGasFilter += tmp_long2;
1512
                                        HoverGasFilter += tmp_long2;
1511
                                }
1513
                                }
1512
                                HooverGas = (int16_t)(HooverGasFilter/HOOVER_GAS_AVERAGE);
1514
                                HoverGas = (int16_t)(HoverGasFilter/HOOVER_GAS_AVERAGE);
1513
                                if(EE_Parameter.Hoehe_HoverBand)
1515
                                if(EE_Parameter.Hoehe_HoverBand)
1514
                                {
1516
                                {
1515
                                        int16_t band;
1517
                                        int16_t band;
1516
                                        band = HooverGas / EE_Parameter.Hoehe_HoverBand; // the higher the parameter the smaller the range
1518
                                        band = HoverGas / EE_Parameter.Hoehe_HoverBand; // the higher the parameter the smaller the range
1517
                                        HooverGasMin = HooverGas - band;
1519
                                        HoverGasMin = HoverGas - band;
1518
                                        HooverGasMax = HooverGas + band;
1520
                                        HoverGasMax = HoverGas + band;
1519
                                }
1521
                                }
1520
                                else
1522
                                else
1521
                                {       // no limit
1523
                                {       // no limit
1522
                                        HooverGasMin = 0;
1524
                                        HoverGasMin = 0;
1523
                                        HooverGasMax = 1023;
1525
                                        HoverGasMax = 1023;
1524
                                }
1526
                                }
1525
                        }
1527
                        }