refactoring: obstacle detection system component separation, partial leverage of new structure

This commit is contained in:
tmj-fstate
2019-02-23 15:26:59 +01:00
parent bc60b5ac62
commit b72e237ab1
8 changed files with 824 additions and 1270 deletions

View File

@@ -1173,7 +1173,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( mvOccupied->Vel < 2.0 ) {
// stanąć nie musi, ale zwolnić przynajmniej
if( ( sSpeedTable[ i ].fDist < fMaxProximityDist )
&& ( TrackBlock() > 1000.0 ) ) {
&& ( Obstacle.distance > 1000 ) ) {
// jest w maksymalnym zasięgu to można go pominąć (wziąć drugą prędkosć)
// as long as there isn't any obstacle in arbitrary view range
eSignSkip = sSpeedTable[ i ].evEvent;
@@ -1259,7 +1259,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
//sprawdzenie eventów pasywnych przed nami
if( ( mvOccupied->CategoryFlag & 1 )
&& ( sSpeedTable[ i ].fDist > pVehicles[ 0 ]->fTrackBlock - 20.0 ) ) {
&& ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) {
// jak sygnał jest dalej niż zawalidroga
v = 0.0; // to może być podany dla tamtego: jechać tak, jakby tam stop był
}
@@ -2061,7 +2061,7 @@ bool TController::CheckVehicles(TOrders user)
&& ( p->MoverParameters->BrakeSubsystem != TBrakeSubSystem::ss_LSt ) ) {
iDrivigFlags &= ~( moveOerlikons );
}
p = p->Neightbour(dir); // pojazd podłączony od wskazanej strony
p = p->Neighbour(dir); // pojazd podłączony od wskazanej strony
}
if (main)
iDrivigFlags |= movePrimary; // nie znaleziono innego, można się porządzić
@@ -2408,11 +2408,11 @@ bool TController::PrepareEngine()
if( !iDirection ) {
// jeśli nie ma ustalonego kierunku
if( ( mvControlling->PantFrontVolt != 0.0 ) || ( mvControlling->PantRearVolt != 0.0 ) || voltfront || voltrear ) {
if( mvOccupied->Couplers[ 1 ].CouplingFlag == coupling::faux ) {
if( mvOccupied->Couplers[ end::rear ].Connected == nullptr ) {
// jeśli z tyłu nie ma nic
iDirection = -1; // jazda w kierunku sprzęgu 1
}
if( mvOccupied->Couplers[ 0 ].CouplingFlag == coupling::faux ) {
if( mvOccupied->Couplers[ end::front ].Connected == nullptr ) {
// jeśli z przodu nie ma nic
iDirection = 1; // jazda w kierunku sprzęgu 0
}
@@ -2618,12 +2618,12 @@ bool TController::IncBrake()
|| ( mvOccupied->TrainType == dt_ET42 ) ) {
// NOTE: we're doing simplified checks full of presuptions here.
// they'll break if someone does strange thing like turning around the second unit
if( ( mvOccupied->Couplers[ 1 ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ 1 ].Connected->Couplers[ 1 ].CouplingFlag > 0 ) ) {
if( ( mvOccupied->Couplers[ end::rear ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ end::rear ].Connected->Couplers[ end::rear ].Connected != nullptr ) ) {
standalone = false;
}
if( ( mvOccupied->Couplers[ 0 ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ 0 ].Connected->Couplers[ 0 ].CouplingFlag > 0 ) ) {
if( ( mvOccupied->Couplers[ end::front ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ end::front ].Connected->Couplers[ end::front ].Connected != nullptr ) ) {
standalone = false;
}
}
@@ -2637,16 +2637,16 @@ bool TController::IncBrake()
( ( mvOccupied->Couplers[ 0 ].CouplingFlag == 0 )
&& ( mvOccupied->Couplers[ 1 ].CouplingFlag == 0 ) );
*/
if( pVehicles[ 0 ] != pVehicles[ 1 ] ) {
if( pVehicles[ end::front ] != pVehicles[ end::rear ] ) {
// more detailed version, will use manual braking also for coupled sets of controlled vehicles
auto *vehicle = pVehicles[ 0 ]; // start from first
auto *vehicle = pVehicles[ end::front ]; // start from first
while( ( true == standalone )
&& ( vehicle != nullptr ) ) {
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
standalone =
( ( ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag & coupling::control ) )
&& ( ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag & coupling::control ) ) );
( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) );
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
}
@@ -3625,22 +3625,21 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
}
WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
}
else // if (NewValue2==0.0) //zerowy sprzęg
if (NewValue1 >= 0.0) // jeśli ilość wagonów inna niż wszystkie
{ // będzie odczepianie, ale jeśli wagony są z przodu, to trzeba najpierw zmienić kierunek
if ((mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 1 : 0].CouplingFlag ==
0) ? // z tyłu nic
(mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 0 : 1].CouplingFlag > 0) :
false) // a z przodu skład
{
iDirectionOrder = -iDirection; // zmiana na ciągnięcie
OrderNext(Change_direction); // najpierw zmień kierunek (zastąpi Disconnect)
OrderPush(Disconnect); // a odczep już po zmianie kierunku
else { // if (NewValue2==0.0) //zerowy sprzęg
if( NewValue1 >= 0.0 ) {
// jeśli ilość wagonów inna niż wszystkie będzie odczepianie,
// ale jeśli wagony są z przodu, to trzeba najpierw zmienić kierunek
if( ( mvOccupied->Couplers[ mvOccupied->DirAbsolute > 0 ? end::rear : end::front ].Connected == nullptr ) // z tyłu nic
&& ( mvOccupied->Couplers[ mvOccupied->DirAbsolute > 0 ? end::front : end::rear ].Connected != nullptr ) ) { // a z przodu skład
iDirectionOrder = -iDirection; // zmiana na ciągnięcie
OrderNext( Change_direction ); // najpierw zmień kierunek (zastąpi Disconnect)
OrderPush( Disconnect ); // a odczep już po zmianie kierunku
}
else if( mvOccupied->Couplers[ mvOccupied->DirAbsolute > 0 ? end::rear : end::front ].Connected != nullptr ) { // z tyłu coś
OrderNext( Disconnect ); // jak ciągnie, to tylko odczep (NewValue1) wagonów
}
WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
}
else if (mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 1 : 0].CouplingFlag >
0) // z tyłu coś
OrderNext(Disconnect); // jak ciągnie, to tylko odczep (NewValue1) wagonów
WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
}
if (NewValue1 == -1.0)
{
@@ -4181,55 +4180,45 @@ TController::UpdateSituation(double dt) {
// 8. Ustalić częstotliwość świadomości AI (zatrzymanie precyzyjne - częściej, brak atrakcji
// - rzadziej).
// check for potential colliders
// check for potential collisions
{
auto rearvehicle = (
pVehicles[ 0 ] == pVehicles[ 1 ] ?
pVehicles[ 0 ] :
pVehicles[ 1 ] );
// HACK: vehicle order in the consist is based on intended travel direction
// if our actual travel direction doesn't match that, we should be scanning from the other end of the consist
auto *frontvehicle { pVehicles[ ( mvOccupied->V * iDirection >= 0 ? end::front : end::rear ) ] };
int routescandirection;
// for moving vehicle determine heading from velocity; for standing fall back on the set direction
if( ( std::abs( mvOccupied->V ) < 0.1 ? // ignore potential micro-stutters in oposite direction during "almost stop"
if( ( std::abs( frontvehicle->MoverParameters->V ) > 0.1 ? // ignore potential micro-stutters in oposite direction during "almost stop"
frontvehicle->MoverParameters->V > 0.0 :
( pVehicle->DirectionGet() == frontvehicle->DirectionGet() ?
iDirection > 0 :
mvOccupied->V > 0.0 ) ) {
iDirection < 0 ) ) ) {
// towards coupler 0
if( ( mvOccupied->V * iDirection < 0.0 )
|| ( ( rearvehicle->NextConnected != nullptr )
&& ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 1 : 0 ) ].CouplingFlag == coupling::faux ) ) ) {
// scan behind if we're moving backward, or if we had something connected there and are moving away
rearvehicle->ABuScanObjects( (
pVehicle->DirectionGet() == rearvehicle->DirectionGet() ?
-1 :
1 ),
fMaxProximityDist );
}
pVehicles[ 0 ]->ABuScanObjects( (
pVehicle->DirectionGet() == pVehicles[ 0 ]->DirectionGet() ?
1 :
-1 ),
routescanrange );
routescandirection = end::front;
}
else {
// towards coupler 1
if( ( mvOccupied->V * iDirection < 0.0 )
|| ( ( rearvehicle->PrevConnected != nullptr )
&& ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 0 : 1 ) ].CouplingFlag == coupling::faux ) ) ) {
// scan behind if we're moving backward, or if we had something connected there and are moving away
rearvehicle->ABuScanObjects( (
pVehicle->DirectionGet() == rearvehicle->DirectionGet() ?
1 :
-1 ),
fMaxProximityDist );
routescandirection = end::rear;
}
Obstacle = neighbour_data();
auto const lookup { frontvehicle->find_vehicle( routescandirection, routescanrange ) };
if( std::get<bool>( lookup ) == true ) {
Obstacle.vehicle = std::get<TDynamicObject *>( lookup );
Obstacle.vehicle_end = std::get<int>( lookup );
Obstacle.distance = std::get<double>( lookup );
if( Obstacle.distance < ( mvOccupied->CategoryFlag == 2 ? 25 : 75 ) ) {
// at short distances (re)calculate range between couplers directly
Obstacle.distance = TMoverParameters::CouplerDist( frontvehicle->MoverParameters, Obstacle.vehicle->MoverParameters );
}
pVehicles[ 0 ]->ABuScanObjects( (
pVehicle->DirectionGet() == pVehicles[ 0 ]->DirectionGet() ?
-1 :
1 ),
routescanrange );
}
else {
Obstacle.distance = 10000; // legacy value. TBD, TODO: use standard -1 instead?
}
}
// tu bedzie logika sterowania
if (AIControllFlag) {
@@ -4291,37 +4280,17 @@ TController::UpdateSituation(double dt) {
if (AIControllFlag)
{ // to robi tylko AI, wersję dla człowieka trzeba dopiero zrobić
// sprzęgi sprawdzamy w pierwszej kolejności, bo jak połączony, to koniec
bool ok; // true gdy się podłączy (uzyskany sprzęg będzie zgodny z żądanym)
if (pVehicles[0]->DirectionGet() > 0) // jeśli sprzęg 0
{ // sprzęg 0 - próba podczepienia
if( pVehicles[ 0 ]->MoverParameters->Couplers[ 0 ].Connected ) {
// jeśli jest coś wykryte (a chyba jest, nie?)
if( pVehicles[ 0 ]->MoverParameters->Attach(
0, 2, pVehicles[ 0 ]->MoverParameters->Couplers[ 0 ].Connected,
iCoupler ) ) {
// pVehicles[0]->dsbCouplerAttach->SetVolume(DSBVOLUME_MAX);
// pVehicles[0]->dsbCouplerAttach->Play(0,0,0);
}
}
// udało się? (mogło częściowo)
ok = (pVehicles[0]->MoverParameters->Couplers[0].CouplingFlag == iCoupler);
}
else // if (pVehicles[0]->MoverParameters->DirAbsolute<0) //jeśli sprzęg 1
{ // sprzęg 1 - próba podczepienia
if( pVehicles[ 0 ]->MoverParameters->Couplers[ 1 ].Connected ) {
// jeśli jest coś wykryte (a chyba jest, nie?)
if( pVehicles[ 0 ]->MoverParameters->Attach(
1, 2, pVehicles[ 0 ]->MoverParameters->Couplers[ 1 ].Connected,
iCoupler ) ) {
// pVehicles[0]->dsbCouplerAttach->SetVolume(DSBVOLUME_MAX);
// pVehicles[0]->dsbCouplerAttach->Play(0,0,0);
}
}
// udało się? (mogło częściowo)
ok = (pVehicles[0]->MoverParameters->Couplers[1].CouplingFlag == iCoupler);
}
if (ok)
{ // jeżeli został podłączony
auto *vehicle { pVehicles[ end::front ] };
auto *vehicleparameters { vehicle->MoverParameters };
int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) };
auto const &neighbour { vehicleparameters->Neighbours[ end ] };
// próba podczepienia
vehicleparameters->Attach(
end, neighbour.vehicle_end,
neighbour.vehicle->MoverParameters,
iCoupler );
if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) {
// jeżeli został podłączony
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie
@@ -4337,7 +4306,7 @@ TController::UpdateSituation(double dt) {
fMaxProximityDist = 5.0; //[m] w takim przedziale odległości powinien stanąć
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
fVelMinus = 1.0; // margines prędkości powodujący załączenie napędu
if( pVehicles[ 0 ]->fTrackBlock <= 20.0 ) {
if( Obstacle.distance <= 20.0 ) {
// przy zderzeniu fTrackBlock nie jest miarodajne
// początek podczepiania, z wyłączeniem sprawdzania fTrackBlock
iDrivigFlags |= moveConnect;
@@ -4477,8 +4446,8 @@ TController::UpdateSituation(double dt) {
&& ( false == TestFlag( iDrivigFlags, movePress ) )
&& ( iCoupler == 0 )
// && ( mvOccupied->Vel > 0.0 )
&& ( pVehicle->MoverParameters->Couplers[ end::front ].CouplingFlag == coupling::faux )
&& ( pVehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag == coupling::faux ) ) {
&& ( pVehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr )
&& ( pVehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) ) {
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
// WriteLog("Zatrzymanie w celu odczepienia");
AccPreferred = std::min( 0.0, AccPreferred );
@@ -4516,7 +4485,7 @@ TController::UpdateSituation(double dt) {
else
{ // samochód ma stać, aż dostanie odjazd, chyba że stoi przez kolizję
if (eStopReason == stopBlock)
if (pVehicles[0]->fTrackBlock > fDriverDist)
if (Obstacle.distance > fDriverDist)
if (AIControllFlag)
{
PrepareEngine(); // zmieni ustawiony kierunek
@@ -4668,7 +4637,8 @@ TController::UpdateSituation(double dt) {
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( p ? p->MoverParameters->Couplers[ d ].CouplingFlag == coupling::faux : true ) {
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
@@ -4759,9 +4729,9 @@ TController::UpdateSituation(double dt) {
// w trybie Connect skanować do tyłu tylko jeśli przed kolejnym sygnałem nie ma taboru do podłączenia
// Ra 2F1H: z tym (fTrackBlock) to nie jest najlepszy pomysł, bo lepiej by
// było porównać z odległością od sygnalizatora z przodu
if( ( OrderList[ OrderPos ] & Connect ) ?
( pVehicles[ 0 ]->fTrackBlock > 2000 || pVehicles[ 0 ]->fTrackBlock > FirstSemaphorDist ) :
true ) {
if( ( ( OrderList[ OrderPos ] & Connect ) == 0 )
|| ( Obstacle.distance > std::min( 2000.0, FirstSemaphorDist ) ) ) {
if( ( comm = BackwardScan() ) != TCommandType::cm_Unknown ) {
// jeśli w drugą można jechać
// należy sprawdzać odległość od znalezionego sygnalizatora,
@@ -4786,121 +4756,99 @@ TController::UpdateSituation(double dt) {
VelDesired = fVelMax; // bo VelDesired<0 oznacza prędkość maksymalną
// Ra: jazda na widoczność
/*
// condition disabled, it'd prevent setting reduced acceleration in the last connect stage
if ((iDrivigFlags & moveConnect) == 0) // przy końcówce podłączania nie hamować
*/
{ // sprawdzenie jazdy na widoczność
auto const vehicle = pVehicles[ 0 ]; // base calculactions off relevant end of the consist
auto const coupler =
vehicle->MoverParameters->Couplers + (
vehicle->DirectionGet() > 0 ?
0 :
1 ); // sprzęg z przodu składu
if( ( coupler->Connected )
&& ( coupler->CouplingFlag == coupling::faux ) ) {
// mamy coś z przodu podłączone sprzęgiem wirtualnym
// wyliczanie optymalnego przyspieszenia do jazdy na widoczność
/*
ActualProximityDist = std::min(
if( Obstacle.distance < 5000 ) {
// mamy coś z przodu
// prędkość pojazdu z przodu (zakładając, że jedzie w tę samą stronę!!!)
auto const k { Obstacle.vehicle->MoverParameters->Vel };
if( k - vel < 5 ) {
// porównanie modułów prędkości [km/h]
// zatroszczyć się trzeba, jeśli tamten nie jedzie znacząco szybciej
ActualProximityDist = std::min<double>(
ActualProximityDist,
vehicle->fTrackBlock - (
mvOccupied->CategoryFlag & 2 ?
fMinProximityDist : // cars can bunch up tighter
fMaxProximityDist ) ); // other vehicle types less so
*/
// prędkość pojazdu z przodu (zakładając, że jedzie w tę samą stronę!!!)
double k = coupler->Connected->Vel;
if( k - vel < 5 ) {
// porównanie modułów prędkości [km/h]
// zatroszczyć się trzeba, jeśli tamten nie jedzie znacząco szybciej
ActualProximityDist = std::min(
ActualProximityDist,
vehicle->fTrackBlock );
Obstacle.distance );
if( ActualProximityDist <= (
( mvOccupied->CategoryFlag & 2 ) ?
100.0 : // cars
250.0 ) ) { // others
// regardless of driving mode at close distance take precaution measures:
// match the other vehicle's speed or slow down if the other vehicle is stopped
VelDesired =
min_speed(
VelDesired,
std::max(
k,
( mvOccupied->CategoryFlag & 2 ) ?
40.0 : // cars
20.0 ) ); // others
if( vel > VelDesired + fVelPlus ) {
// if going too fast force some prompt braking
AccPreferred = std::min( -0.65, AccPreferred );
}
if( ActualProximityDist <= (
( mvOccupied->CategoryFlag & 2 ) ?
100.0 : // cars
250.0 ) ) { // others
// regardless of driving mode at close distance take precaution measures:
// match the other vehicle's speed or slow down if the other vehicle is stopped
VelDesired =
min_speed(
VelDesired,
std::max(
k,
( mvOccupied->CategoryFlag & 2 ) ?
40.0 : // cars
20.0 ) ); // others
if( vel > VelDesired + fVelPlus ) {
// if going too fast force some prompt braking
AccPreferred = std::min( -0.65, AccPreferred );
}
}
double const distance = vehicle->fTrackBlock - fMaxProximityDist - ( fBrakeDist * 1.15 ); // odległość bezpieczna zależy od prędkości
if( distance < 0.0 ) {
// jeśli odległość jest zbyt mała
if( k < 10.0 ) // k - prędkość tego z przodu
{ // jeśli tamten porusza się z niewielką prędkością albo stoi
if( OrderCurrentGet() & Connect ) {
// jeśli spinanie, to jechać dalej
AccPreferred = std::min( 0.35, AccPreferred ); // nie hamuj
VelDesired =
min_speed(
VelDesired,
( vehicle->fTrackBlock > 150.0 ?
20.0:
4.0 ) );
VelNext = 2.0; // i pakuj się na tamtego
}
else {
// a normalnie to hamować
VelNext = 0.0;
if( vehicle->fTrackBlock <= fMinProximityDist ) {
VelDesired = 0.0;
}
if( ( mvOccupied->CategoryFlag & 1 )
&& ( OrderCurrentGet() & Obey_train ) ) {
// trains which move normally should try to stop at safe margin
ActualProximityDist -= fDriverDist;
}
}
}
else {
// jeśli oba jadą, to przyhamuj lekko i ogranicz prędkość
if( vehicle->fTrackBlock < (
( mvOccupied->CategoryFlag & 2 ) ?
fMaxProximityDist + 0.5 * vel : // cars
2.0 * fMaxProximityDist + 2.0 * vel ) ) { //others
// jak tamten jedzie wolniej a jest w drodze hamowania
AccPreferred = std::min( -0.9, AccPreferred );
VelNext = min_speed( std::round( k ) - 5.0, VelDesired );
if( vehicle->fTrackBlock <= (
( mvOccupied->CategoryFlag & 2 ) ?
fMaxProximityDist : // cars
2.0 * fMaxProximityDist ) ) { //others
// try to force speed change if obstacle is really close
VelDesired = VelNext;
}
}
}
ReactionTime = (
mvOccupied->Vel > 0.01 ?
0.1 : // orientuj się, bo jest goraco
2.0 ); // we're already standing still, so take it easy
}
else {
double const distance = Obstacle.distance - fMaxProximityDist - ( fBrakeDist * 1.15 ); // odległość bezpieczna zależy od prędkości
if( distance < 0.0 ) {
// jeśli odległość jest zbyt mała
if( k < 10.0 ) // k - prędkość tego z przodu
{ // jeśli tamten porusza się z niewielką prędkością albo stoi
if( OrderCurrentGet() & Connect ) {
// if there's something nearby in the connect mode don't speed up too much
// jeśli spinanie, to jechać dalej
AccPreferred = std::min( 0.35, AccPreferred ); // nie hamuj
VelDesired =
min_speed(
VelDesired,
( vehicle->fTrackBlock > 100.0 ?
20.0 :
( Obstacle.distance > 150 ?
20.0:
4.0 ) );
VelNext = 2.0; // i pakuj się na tamtego
}
else {
// a normalnie to hamować
VelNext = 0.0;
if( Obstacle.distance <= fMinProximityDist ) {
VelDesired = 0.0;
}
if( ( mvOccupied->CategoryFlag & 1 )
&& ( OrderCurrentGet() & Obey_train ) ) {
// trains which move normally should try to stop at safe margin
ActualProximityDist -= fDriverDist;
}
}
}
else {
// jeśli oba jadą, to przyhamuj lekko i ogranicz prędkość
if( Obstacle.distance < (
( mvOccupied->CategoryFlag & 2 ) ?
fMaxProximityDist + 0.5 * vel : // cars
2.0 * fMaxProximityDist + 2.0 * vel ) ) { //others
// jak tamten jedzie wolniej a jest w drodze hamowania
AccPreferred = std::min( -0.9, AccPreferred );
VelNext = min_speed( std::round( k ) - 5.0, VelDesired );
if( Obstacle.distance <= (
( mvOccupied->CategoryFlag & 2 ) ?
fMaxProximityDist : // cars
2.0 * fMaxProximityDist ) ) { //others
// try to force speed change if obstacle is really close
VelDesired = VelNext;
}
}
}
ReactionTime = (
mvOccupied->Vel > 0.01 ?
0.1 : // orientuj się, bo jest goraco
2.0 ); // we're already standing still, so take it easy
}
else {
if( OrderCurrentGet() & Connect ) {
// if there's something nearby in the connect mode don't speed up too much
VelDesired =
min_speed(
VelDesired,
( Obstacle.distance > 100 ?
20.0 :
4.0 ) );
}
}
}
@@ -5060,7 +5008,7 @@ TController::UpdateSituation(double dt) {
if( mvOccupied->CategoryFlag & 1 ) {
// trains
if( ( OrderCurrentGet() & ( Shunt | Connect ) )
&& ( pVehicles[0]->fTrackBlock < 50.0 ) ) {
&& ( Obstacle.distance < 50 ) ) {
// crude detection of edge case, if approaching another vehicle coast slowly until min distance
// this should allow to bunch up trainsets more on sidings
VelDesired = min_speed( 5.0, VelDesired );
@@ -6344,7 +6292,7 @@ bool TController::IsStop() const
double
TController::TrackBlock() const {
return pVehicles[ end::front ]->fTrackBlock;
return Obstacle.distance;
}
void TController::MoveTo(TDynamicObject *to)

View File

@@ -376,6 +376,7 @@ private:
std::size_t SemNextStopIndex{ std::size_t( -1 ) };
double dMoveLen = 0.0; // odległość przejechana od ostatniego sprawdzenia tabelki
basic_event *eSignNext = nullptr; // sygnał zmieniający prędkość, do pokazania na [F2]
neighbour_data Obstacle; // nearest vehicle detected ahead on current route
// timetable
// methods

File diff suppressed because it is too large Load Diff

View File

@@ -183,12 +183,13 @@ public:
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
Math3D::matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
TMoverParameters *MoverParameters; // parametry fizyki ruchu oraz przeliczanie
TDynamicObject *NextConnected; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
TDynamicObject *PrevConnected; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
int NextConnectedNo; // numer sprzęgu podłączonego z tyłu
int PrevConnectedNo; // numer sprzęgu podłączonego z przodu
double fScanDist; // odległość skanowania torów na obecność innych pojazdów
double fTrackBlock; // odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
inline TDynamicObject *NextConnected() { return MoverParameters->Neighbours[ end::rear ].vehicle; }; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
inline TDynamicObject *PrevConnected() { return MoverParameters->Neighbours[ end::front ].vehicle; }; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
inline TDynamicObject *NextConnected() const { return MoverParameters->Neighbours[ end::rear ].vehicle; }; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
inline TDynamicObject *PrevConnected() const { return MoverParameters->Neighbours[ end::front ].vehicle; }; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
inline int NextConnectedNo() const { return MoverParameters->Neighbours[ end::rear ].vehicle_end; }
inline int PrevConnectedNo() const { return MoverParameters->Neighbours[ end::front ].vehicle_end; }
// double fTrackBlock; // odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
TPowerSource ConnectedEnginePowerSource( TDynamicObject const *Caller ) const;
@@ -455,11 +456,8 @@ private:
int iNumAxles; // ilość osi
std::string asModel;
public:
void ABuScanObjects(int ScanDir, double ScanDist);
private:
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler );
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler ) const;
void ABuCheckMyTrack();
public:
@@ -470,7 +468,6 @@ private:
TDynamicObject * Next();
TDynamicObject * PrevC(int C);
TDynamicObject * NextC(int C);
double NextDistance(double d = -1.0);
void SetdMoveLen(double dMoveLen) {
MoverParameters->dMoveLen = dMoveLen; }
void ResetdMoveLen() {
@@ -485,6 +482,7 @@ private:
return this ?
asName :
std::string(); };
std::string asBaseDir;
// std::ofstream PneuLogFile; //zapis parametrow pneumatycznych
// youBy - dym
@@ -506,7 +504,6 @@ private:
bool bDisplayCab; // czy wyswietlac kabine w train.cpp
int iCabs; // maski bitowe modeli kabin
TTrack *MyTrack; // McZapkie-030303: tor na ktorym stoi, ABu
std::string asBaseDir;
int iOverheadMask; // maska przydzielana przez AI pojazdom posiadającym pantograf, aby wymuszały jazdę bezprądową
TTractionParam tmpTraction;
double fAdjustment; // korekcja - docelowo przenieść do TrkFoll.cpp wraz z odległością od poprzedniego
@@ -521,7 +518,7 @@ private:
int init_sections( TModel3d const *Model, std::string const &Nameprefix );
void create_controller( std::string const Type, bool const Trainset );
void AttachPrev(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt, double dt1, bool FullVer);
bool UpdateForce(double dt);
// initiates load change by specified amounts, with a platform on specified side
void LoadExchange( int const Disembark, int const Embark, int const Platform );
// calculates time needed to complete current load change
@@ -605,14 +602,13 @@ private:
Axle1.GetTranslation() :
Axle0.GetTranslation(); };
// zwraca tor z aktywną osią
inline TTrack * RaTrackGet() {
inline TTrack * RaTrackGet() const {
return iAxleFirst ?
Axle1.GetTrack() :
Axle0.GetTrack(); };
void couple( int const Side );
int uncouple( int const Side );
void CouplersDettach(double MinDist, int MyScanDir);
void RadioStop();
void Damage(char flag);
void RaLightsSet(int head, int rear);
@@ -626,8 +622,11 @@ private:
return iDirection + iDirection - 1; };
int DettachStatus(int dir);
int Dettach(int dir);
TDynamicObject * Neightbour(int &dir);
void CoupleDist();
TDynamicObject * Neighbour(int &dir);
// updates potential collision sources
void update_neighbours();
// locates potential collision source within specified range, scanning its route in specified direction
auto find_vehicle( int const Direction, double const Range ) const -> std::tuple<TDynamicObject *, int, double, bool>;
TDynamicObject * ControlledFind();
void ParamSet(int what, int into);
// zapytanie do AI, po którym segmencie skrzyżowania jechać

View File

@@ -140,7 +140,7 @@ static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłyc
// vehicle sides; exclusive
enum end {
front = 0,
rear
rear = 1
};
enum side {
@@ -609,18 +609,16 @@ struct power_coupling {
struct TCoupling {
/*parametry*/
double SpringKB = 1.0; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */
double SpringKC = 1.0;
double beta = 0.0;
double DmaxB = 0.1; /*tolerancja scisku/rozciagania, sila rozerwania*/
double FmaxB = 1000.0;
double SpringKC = 1.0;
double DmaxC = 0.1;
double FmaxC = 1000.0;
TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/
/*zmienne*/
double beta = 0.0;
TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/
int AllowedFlag = 3; //Ra: maska dostępnych
/*zmienne*/
int CouplingFlag = 0; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/
int AllowedFlag = 3; //Ra: znaczenie jak wyżej, maska dostępnych
bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/
double CoupleDist = 0.0; /*ABu: optymalizacja - liczenie odleglosci raz na klatkę, bez iteracji*/
class TMoverParameters *Connected = nullptr; /*co jest podlaczone*/
int ConnectedNr = 0; //Ra: od której strony podłączony do (Connected): 0=przód, 1=tył
double CForce = 0.0; /*sila z jaka dzialal*/
@@ -628,16 +626,25 @@ struct TCoupling {
bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/
power_coupling power_high;
power_coupling power_low; // TODO: implement this
// power_coupling power_low; // TODO: implement this
int sounds { 0 }; // sounds emitted by the coupling devices
bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/
};
struct neighbour_data {
TDynamicObject *vehicle { nullptr }; // detected obstacle
int vehicle_end { -1 }; // facing end of the obstacle
float distance { -1.f }; // distance to the obstacle
};
class TMoverParameters
{ // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :)
private:
// types
/* TODO: implement
// communication cable, exchanging control signals with adjacent vehicle
struct jumper_cable {
// types
@@ -651,7 +658,7 @@ private:
// integers
// std::array<int, 1> values {};
};
*/
// basic approximation of a generic device
// TBD: inheritance or composition?
struct basic_device {
@@ -818,14 +825,12 @@ private:
public:
double dMoveLen = 0.0;
std::string filename;
/*---opis lokomotywy, wagonu itp*/
/*--opis serii--*/
int CategoryFlag = 1; /*1 - pociag, 2 - samochod, 4 - statek, 8 - samolot*/
/*--sekcja stalych typowych parametrow*/
std::string TypeName; /*nazwa serii/typu*/
//TrainType: string; {typ: EZT/elektrowoz - Winger 040304}
int TrainType = 0; /*Ra: powinno być szybciej niż string*/
int TrainType = 0; /*typ: EZT/elektrowoz - Winger 040304 Ra: powinno być szybciej niż string*/
TEngineType EngineType = TEngineType::None; /*typ napedu*/
TPowerParameters EnginePowerSource; /*zrodlo mocy dla silnikow*/
TPowerParameters SystemPowerSource; /*zrodlo mocy dla systemow sterowania/przetwornic/sprezarek*/
@@ -1077,6 +1082,7 @@ public:
TRotation Rot { 0.0, 0.0, 0.0 };
std::string Name; /*nazwa wlasna*/
TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
std::array<neighbour_data, 2> Neighbours; // potential collision sources
bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/
int SoundFlag = 0; /*!o patrz stale sound_ */
double DistCounter = 0.0; /*! licznik kilometrow */
@@ -1307,24 +1313,19 @@ public:
double FrictConst2d= 0.0;
double TotalMassxg = 0.0; /*TotalMass*g*/
Math3D::vector3 vCoulpler[2]; // powtórzenie współrzędnych sprzęgów z DynObj :/
double fBrakeCtrlPos = -2.0; // płynna nastawa hamulca zespolonego
bool bPantKurek3 = true; // kurek trójdrogowy (pantografu): true=połączenie z ZG, false=połączenie z małą sprężarką // domyślnie zbiornik pantografu połączony jest ze zbiornikiem głównym
int iProblem = 0; // flagi problemów z taborem, aby AI nie musiało porównywać; 0=może jechać
int iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu
private:
double CouplerDist(int Coupler);
public:
TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab);
// obsługa sprzęgów
double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2);
/* double Distance(const vector3 &Loc1, const vector3 &Loc2, const vector3 &Dim1, const vector3 &Dim2);
*/ //bool AttachA(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false);
static double CouplerDist( TMoverParameters const *Left, TMoverParameters const *Right );
static double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2);
bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false, bool Audible = true);
int DettachStatus(int ConnectNo);
bool Dettach(int ConnectNo);
void SetCoupleDist();
bool DirectionForward();
void BrakeLevelSet(double b);
bool BrakeLevelAdd(double b);
@@ -1340,7 +1341,7 @@ public:
// Q *******************************************************************************************
double GetTrainsetVoltage(void);
bool Physic_ReActivation(void);
bool switch_physics(bool const State);
double LocalBrakeRatio(void);
double ManualBrakeRatio(void);
double PipeRatio(void);/*ile napelniac*/
@@ -1412,17 +1413,17 @@ public:
/*funkcje obliczajace sily*/
void ComputeConstans(void);//ABu: wczesniejsze wyznaczenie stalych dla liczenia sil
double ComputeMass(void);
void ComputeTotalForce(double dt, double dt1, bool FullVer);
void ComputeTotalForce(double dt);
double Adhesive(double staticfriction) const;
double TractionForce(double dt);
double FrictionForce(double R, int TDamage);
double BrakeForceR(double ratio, double velocity);
double BrakeForceP(double press, double velocity);
double BrakeForce(const TTrackParam &Track);
double CouplerForce(int CouplerN, double dt);
double CouplerForce(int const End, double dt);
void CollisionDetect(int CouplerN, double dt);
/*obrot kol uwzgledniajacy poslizg*/
double ComputeRotatingWheel(double WForce, double dt, double n);
double ComputeRotatingWheel(double WForce, double dt, double n) const;
/*--funkcje dla lokomotyw*/
bool DirectionBackward(void);/*! kierunek ruchu*/

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h"
#include "MOVER.h"
#include "DynObj.h"
#include "Oerlikon_ESt.h"
#include "utilities.h"
#include "Globals.h"
@@ -383,168 +384,118 @@ double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2,
{ // zwraca odległość pomiędzy pojazdami (Loc1) i (Loc2) z uwzględnieneim ich długości (kule!)
return hypot(Loc2.X - Loc1.X, Loc1.Y - Loc2.Y) - 0.5 * (Dim2.L + Dim1.L);
};
/*
double TMoverParameters::Distance(const vector3 &s1, const vector3 &s2, const vector3 &d1,
const vector3 &d2){
// obliczenie odległości prostopadłościanów o środkach (s1) i (s2) i wymiarach (d1) i (d2)
// return 0.0; //będzie zgłaszać warning - funkcja do usunięcia, chyba że się przyda...
};
*/
double TMoverParameters::CouplerDist(int Coupler)
{ // obliczenie odległości pomiędzy sprzęgami (kula!)
Couplers[Coupler].CoupleDist =
Distance(
Loc, Couplers[Coupler].Connected->Loc,
Dim, Couplers[Coupler].Connected->Dim); // odległość pomiędzy sprzęgami (kula!)
return Couplers[ Coupler ].CoupleDist;
double TMoverParameters::CouplerDist(TMoverParameters const *Left, TMoverParameters const *Right)
{ // obliczenie odległości pomiędzy sprzęgami (kula!)
return
Distance(
Left->Loc, Right->Loc,
Left->Dim, Right->Dim); // odległość pomiędzy sprzęgami (kula!)
};
bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced, bool Audible)
{ //łączenie do swojego sprzęgu (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr)
// Ra: zwykle wykonywane dwukrotnie, dla każdego pojazdu oddzielnie
// Ra: trzeba by odróżnić wymóg dociśnięcia od uszkodzenia sprzęgu przy podczepianiu AI do
// składu
if (ConnectTo) // jeśli nie pusty
{
auto &coupler = Couplers[ ConnectNo ];
if (ConnectToNr != 2)
coupler.ConnectedNr = ConnectToNr; // 2=nic nie podłączone
coupler.Connected = ConnectTo; // tak podpiąć (do siebie) zawsze można, najwyżej będzie wirtualny
CouplerDist( ConnectNo ); // przeliczenie odległości pomiędzy sprzęgami
// Ra: trzeba by odróżnić wymóg dociśnięcia od uszkodzenia sprzęgu przy podczepianiu AI do składu
if (CouplingType == coupling::faux)
return false; // wirtualny więcej nic nie robi
auto &othercoupler = ConnectTo->Couplers[ coupler.ConnectedNr ];
if( ( Forced )
|| ( ( coupler.CoupleDist <= dEpsilon )
&& ( coupler.CouplerType != TCouplerType::NoCoupler )
&& ( coupler.CouplerType == othercoupler.CouplerType ) ) )
{ // stykaja sie zderzaki i kompatybilne typy sprzegow, chyba że łączenie na starcie
if( coupler.CouplingFlag == ctrain_virtual ) {
// jeśli wcześniej nie było połączone, ustalenie z której strony rysować sprzęg
coupler.Render = true; // tego rysować
othercoupler.Render = false; // a tego nie
};
auto const couplingchange { CouplingType ^ coupler.CouplingFlag };
coupler.CouplingFlag = CouplingType; // ustawienie typu sprzęgu
// if (CouplingType!=ctrain_virtual) //Ra: wirtualnego nie łączymy zwrotnie!
//{//jeśli łączenie sprzęgiem niewirtualnym, ustawiamy połączenie zwrotne
othercoupler.CouplingFlag = CouplingType;
othercoupler.Connected = this;
othercoupler.CoupleDist = coupler.CoupleDist;
if( ( true == Audible ) && ( couplingchange != 0 ) ) {
// set sound event flag
int soundflag{ sound::none };
std::vector<std::pair<coupling, sound>> const soundmappings = {
{ coupling::coupler, sound::attachcoupler },
{ coupling::brakehose, sound::attachbrakehose },
{ coupling::mainhose, sound::attachmainhose },
{ coupling::control, sound::attachcontrol},
{ coupling::gangway, sound::attachgangway},
{ coupling::heating, sound::attachheating} };
for( auto const &soundmapping : soundmappings ) {
if( ( couplingchange & soundmapping.first ) != 0 ) {
soundflag |= soundmapping.second;
}
}
SetFlag( coupler.sounds, soundflag );
}
return true;
//}
// podłączenie nie udało się - jest wirtualne
}
if( ( ConnectTo == nullptr )
|| ( CouplingType == coupling::faux ) ) {
return false;
}
return false; // brak podłączanego pojazdu, zbyt duża odległość, niezgodny typ sprzęgu, brak
// sprzęgu, brak haka
};
auto &coupler { Couplers[ ConnectNo ] };
auto &othercoupler = ConnectTo->Couplers[ ( ConnectToNr != 2 ? ConnectToNr : coupler.ConnectedNr ) ];
auto const distance { CouplerDist( this, ConnectTo ) };
// to jest już niepotrzebne bo nie ma Delphi
//bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo,
// int CouplingType, bool Forced)
//{ //łączenie do (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr)
// return Attach(ConnectNo, ConnectToNr, (TMoverParameters *)ConnectTo, CouplingType, Forced);
//};
auto const couplercheck {
( Forced )
|| ( ( distance <= dEpsilon )
&& ( coupler.CouplerType != TCouplerType::NoCoupler )
&& ( coupler.CouplerType == othercoupler.CouplerType ) ) };
if( false == couplercheck ) { return false; }
// stykaja sie zderzaki i kompatybilne typy sprzegow, chyba że łączenie na starcie
if( coupler.CouplingFlag == coupling::faux ) {
// jeśli wcześniej nie było połączone, ustalenie z której strony rysować sprzęg
coupler.Render = true; // tego rysować
othercoupler.Render = false; // a tego nie
};
auto const couplingchange { CouplingType ^ coupler.CouplingFlag };
coupler.Connected = ConnectTo;
coupler.CouplingFlag = CouplingType; // ustawienie typu sprzęgu
if( ConnectToNr != 2 ) {
coupler.ConnectedNr = ConnectToNr; // 2=nic nie podłączone
}
othercoupler.Connected = this;
othercoupler.CouplingFlag = CouplingType;
othercoupler.ConnectedNr = ConnectNo;
if( ( true == Audible ) && ( couplingchange != 0 ) ) {
// set sound event flag
int soundflag{ sound::none };
std::vector<std::pair<coupling, sound>> const soundmappings = {
{ coupling::coupler, sound::attachcoupler },
{ coupling::brakehose, sound::attachbrakehose },
{ coupling::mainhose, sound::attachmainhose },
{ coupling::control, sound::attachcontrol},
{ coupling::gangway, sound::attachgangway},
{ coupling::heating, sound::attachheating} };
for( auto const &soundmapping : soundmappings ) {
if( ( couplingchange & soundmapping.first ) != 0 ) {
soundflag |= soundmapping.second;
}
}
SetFlag( coupler.sounds, soundflag );
}
return true;
}
int TMoverParameters::DettachStatus(int ConnectNo)
{ // Ra: sprawdzenie, czy odległość jest dobra do rozłączania
// powinny być 3 informacje: =0 sprzęg już rozłączony, <0 da się rozłączyć. >0 nie da się
// rozłączyć
// powinny być 3 informacje: =0 sprzęg już rozłączony, <0 da się rozłączyć. >0 nie da się rozłączyć
if (!Couplers[ConnectNo].Connected)
return 0; // nie ma nic, to rozłączanie jest OK
if ((Couplers[ConnectNo].CouplingFlag & ctrain_coupler) == 0)
return -Couplers[ConnectNo].CouplingFlag; // hak nie połączony - rozłączanie jest OK
if (TestFlag(DamageFlag, dtrain_coupling))
return -Couplers[ConnectNo].CouplingFlag; // hak urwany - rozłączanie jest OK
// ABu021104: zakomentowane 'and (CouplerType<>Articulated)' w warunku, nie wiem co to bylo, ale
// za to teraz dziala odczepianie... :) }
// if (CouplerType==Articulated) return false; //sprzęg nie do rozpięcia - może być tylko urwany
// Couplers[ConnectNo].CoupleDist=Distance(Loc,Couplers[ConnectNo].Connected->Loc,Dim,Couplers[ConnectNo].Connected->Dim);
CouplerDist(ConnectNo);
if (Couplers[ConnectNo].CouplerType == TCouplerType::Screw ? Couplers[ConnectNo].CoupleDist < 0.01 : true)
// CouplerDist(ConnectNo);
if (Couplers[ConnectNo].CouplerType == TCouplerType::Screw ? Neighbours[ConnectNo].distance < 0.01 : true)
return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty
return (Couplers[ConnectNo].CoupleDist > 0.2) ? -Couplers[ConnectNo].CouplingFlag :
return (Neighbours[ConnectNo].distance > 0.2) ? -Couplers[ConnectNo].CouplingFlag :
Couplers[ConnectNo].CouplingFlag;
};
bool TMoverParameters::Dettach(int ConnectNo)
{ // rozlaczanie
if (!Couplers[ConnectNo].Connected)
return true; // nie ma nic, to odczepiono
// with Couplers[ConnectNo] do
int i = DettachStatus(ConnectNo); // stan sprzęgu
if (i < 0)
{ // gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony)
// Couplers[ConnectNo].Connected=NULL; //lepiej zostawic bo przeciez trzeba kontrolowac
// zderzenia odczepionych
Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag =
0; // pozostaje sprzęg wirtualny
Couplers[ConnectNo].CouplingFlag = 0; // pozostaje sprzęg wirtualny
auto &coupler { Couplers[ ConnectNo ] };
auto &othervehicle { coupler.Connected };
auto &othercoupler { othervehicle->Couplers[ coupler.ConnectedNr ] };
if( othervehicle == nullptr ) { return true; } // nie ma nic, to odczepiono
auto const i = DettachStatus(ConnectNo); // stan sprzęgu
if (i < 0) {
// gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony)
std::tie( coupler.Connected, coupler.ConnectedNr, coupler.CouplingFlag )
= std::tie( othercoupler.Connected, othercoupler.ConnectedNr, othercoupler.CouplingFlag )
= std::make_tuple( nullptr, -1, coupling::faux );
// set sound event flag
SetFlag( Couplers[ ConnectNo ].sounds, sound::detachall );
SetFlag( coupler.sounds, sound::detachall );
return true;
}
else if (i > 0)
{ // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym
// nic)
Couplers[ConnectNo].CouplingFlag &= ctrain_coupler;
Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag =
Couplers[ConnectNo].CouplingFlag;
{ // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym nic)
coupler.CouplingFlag &= coupling::coupler;
othercoupler.CouplingFlag &= coupling::coupler;
}
return false; // jeszcze nie rozłączony
};
// przeliczenie odległości sprzęgów
void TMoverParameters::SetCoupleDist() {
/*
double const MaxDist = 100.0; // 2x average max proximity distance. TODO: rearrange ito something more elegant
*/
for( int coupleridx = 0; coupleridx <= 1; ++coupleridx ) {
if( Couplers[ coupleridx ].Connected == nullptr ) { continue; }
CouplerDist( coupleridx );
if( CategoryFlag & 2 ) {
// Ra: dla samochodów zderzanie kul to za mało
// NOTE: whatever calculation was supposed to be here, ain't
}
/*
if( ( Couplers[ coupleridx ].CouplingFlag == coupling::faux )
&& ( Couplers[ coupleridx ].CoupleDist > MaxDist ) ) {
// zerwij kontrolnie wirtualny sprzeg
// Connected.Couplers[CNext].Connected:=nil; //Ra: ten podłączony niekoniecznie jest wirtualny
Couplers[ coupleridx ].Connected = nullptr;
Couplers[ coupleridx ].ConnectedNr = 2;
}
*/
}
};
bool TMoverParameters::DirectionForward()
{
if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos == 0))
@@ -1064,7 +1015,8 @@ void TMoverParameters::CollisionDetect(int CouplerN, double dt)
CCF =
ComputeCollision(
coupler.Connected->V,
V, coupler.Connected->TotalMass,
V,
coupler.Connected->TotalMass,
TotalMass,
(coupler.beta + coupler.Connected->Couplers[coupler.ConnectedNr].beta) / 2.0,
VirtualCoupling)
@@ -3755,7 +3707,7 @@ void TMoverParameters::UpdateScndPipePressure(double dt)
c = Couplers[0].Connected; // skrot
dv1 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75);
if (dv1 * dv1 > 0.00000000000001)
c->Physic_ReActivation();
c->switch_physics( true );
c->Pipe2->Flow(-dv1);
}
// sprzeg 2
@@ -3765,7 +3717,7 @@ void TMoverParameters::UpdateScndPipePressure(double dt)
c = Couplers[1].Connected; // skrot
dv2 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75);
if (dv2 * dv2 > 0.00000000000001)
c->Physic_ReActivation();
c->switch_physics( true );
c->Pipe2->Flow(-dv2);
}
if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL))
@@ -3816,7 +3768,7 @@ double TMoverParameters::GetDVc(double dt)
c = Couplers[0].Connected; // skrot //0.08 //e/D * L/D = e/D^2 * L
dv1 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1.0 + 0.015 / Spg * Dim.L));
if (dv1 * dv1 > 0.00000000000001)
c->Physic_ReActivation();
c->switch_physics( true );
c->Pipe->Flow(-dv1);
}
// sprzeg 2
@@ -3826,7 +3778,7 @@ double TMoverParameters::GetDVc(double dt)
c = Couplers[1].Connected; // skrot
dv2 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1.0 + 0.015 / Spg * Dim.L));
if (dv2 * dv2 > 0.00000000000001)
c->Physic_ReActivation();
c->switch_physics( true );
c->Pipe->Flow(-dv2);
}
//if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL))
@@ -3922,143 +3874,138 @@ double TMoverParameters::ComputeMass(void)
// Q: 20160713
// Obliczanie wypadkowej siły z wszystkich działających sił
// *************************************************************************************************
void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
{
int b;
double Fwheels = 0.0;
// TBD, TODO: move some of the calculations out of the method, they're relevant to more than just force calculations
void TMoverParameters::ComputeTotalForce(double dt) {
if (PhysicActivation)
{
// EventFlag:=false; {jesli cos sie zlego
// wydarzy to ustawiane na true}
// SoundFlag:=0; {jesli ma byc jakis dzwiek
// to zapalany jet odpowiedni bit}
// to powinno byc zerowane na zewnatrz
// juz zoptymalizowane:
FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu
Vel = abs(V) * 3.6; // prędkość w km/h
nrot = v2n(); // przeliczenie prędkości liniowej na obrotową
if( (true == TestFlag(BrakeMethod, bp_MHS))
&& (PipePress < 3.0)
&& (Vel > 45)
&& (true == TestFlag(BrakeDelayFlag, bdelay_M))) // ustawione na sztywno na 3 bar
FStand += TrackBrakeForce; // doliczenie hamowania hamulcem szynowym
// w charakterystykach jest wartość siły hamowania zamiast nacisku
// if(FullVer=true) then
// ABu: to dla optymalizacji, bo chyba te rzeczy wystarczy sprawdzac 1 raz na
// klatke?
LastSwitchingTime += dt1;
if (EngineType == TEngineType::ElectricSeriesMotor)
LastRelayTime += dt1;
if( Mains && /*(abs(CabNo) < 2) &&*/ ( EngineType == TEngineType::ElectricSeriesMotor ) ) // potem ulepszyc! pantogtrafy!
{ // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być
// zdefiniowany nawrotnik
if( CabNo == 0 )
Voltage = RunningTraction.TractionVoltage * ActiveDir;
else
Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo;
} // bo nie dzialalo
else if( ( EngineType == TEngineType::ElectricInductionMotor )
|| ( ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) == ctrain_power )
|| ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) {
// potem ulepszyc! pantogtrafy!
Voltage =
std::max(
RunningTraction.TractionVoltage,
std::max(
Couplers[ end::front ].power_high.voltage,
Couplers[ end::rear ].power_high.voltage ) );
}
else {
Voltage = 0;
}
if (Power > 0)
FTrain = TractionForce(dt);
else
FTrain = 0;
Fb = BrakeForce(RunningTrack);
Fwheels = FTrain - Fb * Sign(V);
if( ( Vel > 0.001 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test
&& ( std::abs(Fwheels) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) // poslizg
{
SlippingWheels = true;
}
if( true == SlippingWheels ) {
// TrainForce:=TrainForce-Fb;
double temp_nrot = ComputeRotatingWheel(Fwheels -
Sign(nrot * M_PI * WheelDiameter - V) *
Adhesive(RunningTrack.friction) * TotalMassxg,
dt, nrot);
Fwheels = Sign(temp_nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction);
if (Fwheels*Sign(V)>0)
{
FTrain = Fwheels + Fb*Sign(V);
}
else if (FTrain*Sign(V)>0)
{
Fb = FTrain*Sign(V) - Fwheels*Sign(V);
}
else
{
Fb = -Fwheels*Sign(V);
FTrain = 0;
}
if (nrot < 0.1)
{
WheelFlat = sqrt(square(WheelFlat) + abs(Fwheels) / NAxles*Vel*0.000002);
}
if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0)
{
SlippingWheels = false;
temp_nrot = V / M_PI / WheelDiameter;
}
nrot = temp_nrot;
}
// else SlippingWheels:=false;
// FStand:=0;
for (b = 0; b < 2; ++b)
if (Couplers[b].Connected != NULL) /*and (Couplers[b].CouplerType<>Bare) and
(Couplers[b].CouplerType<>Articulated)*/
{ // doliczenie sił z innych pojazdów
Couplers[b].CForce = CouplerForce(b, dt);
FTrain += Couplers[b].CForce;
}
else
Couplers[b].CForce = 0;
// FStand:=Fb+FrictionForce(RunningShape.R,RunningTrack.DamageFlag);
FStand += Fb;
FTrain +=
TotalMassxg * RunningShape.dHtrack; // doliczenie składowej stycznej grawitacji
//!niejawne przypisanie zmiennej!
FTotal = FTrain - Sign(V) * FStand;
}
Vel = std::abs(V) * 3.6; // prędkość w km/h
// McZapkie-031103: sprawdzanie czy warto liczyc fizyke i inne updaty
// ABu 300105: cos tu mieszalem , dziala teraz troche lepiej, wiec zostawiam
if ((CabNo == 0) && (Vel < 0.0001) && (abs(AccS) < 0.0001) && (TrainType != dt_EZT))
{
if (!PhysicActivation)
{
if (Couplers[0].Connected != NULL)
if ((Couplers[0].Connected->Vel > 0.0001) ||
(abs(Couplers[0].Connected->AccS) > 0.0001))
Physic_ReActivation();
if (Couplers[1].Connected != NULL)
if ((Couplers[1].Connected->Vel > 0.0001) ||
(abs(Couplers[1].Connected->AccS) > 0.0001))
Physic_ReActivation();
}
if (LastSwitchingTime > 5) // 10+Random(100) then
PhysicActivation = false; // zeby nie brac pod uwage braku V po uruchomieniu programu
auto const vehicleisactive {
( CabNo != 0 )
|| ( Vel > 0.0001 )
|| ( std::abs( AccS ) > 0.0001 )
|| ( LastSwitchingTime < 5 )
|| ( TrainType == dt_EZT )
|| ( TrainType == dt_DMU ) };
auto const movingvehicleahead {
( Neighbours[ end::front ].vehicle != nullptr )
&& ( ( Neighbours[ end::front ].vehicle->MoverParameters->Vel > 0.0001 )
|| ( std::abs( Neighbours[ end::front ].vehicle->MoverParameters->AccS ) > 0.0001 ) ) };
auto const movingvehiclebehind {
( Neighbours[ end::rear ].vehicle != nullptr )
&& ( ( Neighbours[ end::rear ].vehicle->MoverParameters->Vel > 0.0001 )
|| ( std::abs( Neighbours[ end::rear ].vehicle->MoverParameters->AccS ) > 0.0001 ) ) };
auto const calculatephysics { vehicleisactive || movingvehicleahead || movingvehiclebehind };
switch_physics( calculatephysics );
}
else
PhysicActivation = true;
if( false == PhysicActivation ) { return; }
// juz zoptymalizowane:
FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu
nrot = v2n(); // przeliczenie prędkości liniowej na obrotową
if( ( true == TestFlag( BrakeMethod, bp_MHS ) )
&& ( PipePress < 3.0 ) // ustawione na sztywno na 3 bar
&& ( Vel > 45 )
&& ( true == TestFlag( BrakeDelayFlag, bdelay_M ) ) ) {
// doliczenie hamowania hamulcem szynowym
FStand += TrackBrakeForce;
}
// w charakterystykach jest wartość siły hamowania zamiast nacisku
LastSwitchingTime += dt;
if( EngineType == TEngineType::ElectricSeriesMotor ) {
LastRelayTime += dt;
}
if( Mains && /*(abs(CabNo) < 2) &&*/ ( EngineType == TEngineType::ElectricSeriesMotor ) ) // potem ulepszyc! pantogtrafy!
{ // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik
if( CabNo == 0 )
Voltage = RunningTraction.TractionVoltage * ActiveDir;
else
Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo;
} // bo nie dzialalo
else if( ( EngineType == TEngineType::ElectricInductionMotor )
|| ( ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) == ctrain_power )
|| ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) {
// potem ulepszyc! pantogtrafy!
Voltage =
std::max(
RunningTraction.TractionVoltage,
std::max(
Couplers[ end::front ].power_high.voltage,
Couplers[ end::rear ].power_high.voltage ) );
}
else {
Voltage = 0;
}
FTrain = (
Power > 0 ?
TractionForce( dt ) :
0 );
Fb = BrakeForce(RunningTrack);
// poslizg
auto Fwheels { FTrain - Fb * Sign( V ) };
if( ( Vel > 0.001 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test
&& ( std::abs(Fwheels) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) {
SlippingWheels = true;
}
if( true == SlippingWheels ) {
double temp_nrot = ComputeRotatingWheel(Fwheels -
Sign(nrot * M_PI * WheelDiameter - V) *
Adhesive(RunningTrack.friction) * TotalMassxg,
dt, nrot);
Fwheels = Sign(temp_nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction);
if (Fwheels*Sign(V)>0)
{
FTrain = Fwheels + Fb*Sign(V);
}
else if (FTrain*Sign(V)>0)
{
Fb = FTrain*Sign(V) - Fwheels*Sign(V);
}
else
{
Fb = -Fwheels*Sign(V);
FTrain = 0;
}
if (nrot < 0.1)
{
WheelFlat = sqrt(square(WheelFlat) + abs(Fwheels) / NAxles*Vel*0.000002);
}
if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0)
{
SlippingWheels = false;
temp_nrot = V / M_PI / WheelDiameter;
}
nrot = temp_nrot;
}
// doliczenie sił z innych pojazdów
for( int end = end::front; end <= end::rear; ++end ) {
if( Neighbours[ end ].vehicle != nullptr ) {
Couplers[ end ].CForce = CouplerForce( end, dt );
FTrain += Couplers[ end ].CForce;
}
else
Couplers[ end ].CForce = 0;
}
FStand += Fb;
// doliczenie składowej stycznej grawitacji
FTrain += TotalMassxg * RunningShape.dHtrack;
//!niejawne przypisanie zmiennej!
FTotal = FTrain - Sign(V) * FStand;
}
double TMoverParameters::BrakeForceR(double ratio, double velocity)
@@ -4235,175 +4182,121 @@ double TMoverParameters::Adhesive(double staticfriction) const
return adhesion;
}
// poprawka dla liczenia sil przy ustawieniu przeciwnym obiektow:
/*
double DirPatch(int Coupler1, int Coupler2)
{
if (Coupler1 != Coupler2) return 1;
else return -1;
}
double DirF(int CouplerN)
{
double rDirF;
switch (CouplerN)
{
case 0: return -1; break;
case 1: return 1; break;
default: return 0;
}
// if (CouplerN == 0) return -1;
// else if (CouplerN == 0) return 1;
// else return 0;
}
*/
// *************************************************************************************************
// Q: 20160713
// Obliczanie sił dzialających na sprzęgach
// *************************************************************************************************
double TMoverParameters::CouplerForce(int CouplerN, double dt)
{
// wyliczenie siły na sprzęgu
double tempdist = 0, newdist = 0, distDelta = 0, CF = 0, dV = 0, absdV = 0, Fmax = 0;
double BetaAvg = 0;
int CNext = 0;
const double MaxDist = 405.0; // ustawione + 5 m, bo skanujemy do 400 m
const double MinDist = 0.5; // ustawione +.5 m, zeby nie rozlaczac przy malych odleglosciach
const int MaxCount = 1500;
bool rCF = false;
// distDelta:=0; //Ra: value never used
CNext = Couplers[CouplerN].ConnectedNr;
// if (Couplers[CouplerN].CForce == 0) //nie bylo uzgadniane wiec policz
double TMoverParameters::CouplerForce( int const End, double dt ) {
Couplers[CouplerN].CheckCollision = false;
newdist = Couplers[CouplerN].CoupleDist; // odległość od sprzęgu sąsiada
// newdist:=Distance(Loc,Connected^.Loc,Dim,Connected^.Dim);
if (CouplerN == 0)
{
// ABu: bylo newdist+10*((...
tempdist = ((Couplers[CouplerN].Connected->dMoveLen *
DirPatch(0, Couplers[CouplerN].ConnectedNr)) -
dMoveLen);
newdist += 10.0 * tempdist;
// tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu
}
else
{
// ABu: bylo newdist+10*((...
tempdist = ((dMoveLen - (Couplers[CouplerN].Connected->dMoveLen *
DirPatch(1, Couplers[CouplerN].ConnectedNr))));
newdist += 10.0 * tempdist;
// tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu
}
auto &coupler { Couplers[ End ] };
auto *othervehicle { Neighbours[ End ].vehicle->MoverParameters };
auto const otherend { Neighbours[ End ].vehicle_end };
auto &othercoupler { othervehicle->Couplers[ otherend ] };
auto const othervehiclemove { ( othervehicle->dMoveLen * DirPatch( End, otherend ) ) };
auto const distancedelta { (
End == end::front ?
othervehiclemove - dMoveLen :
dMoveLen - othervehiclemove ) };
auto const initialdistance { Neighbours[ End ].distance }; // odległość od sprzęgu sąsiada
auto const newdistance =
initialdistance
+ 10.0 * distancedelta;
auto const dV { V - ( othervehicle->V * DirPatch( End, otherend ) ) };
auto const absdV { std::abs( dV ) };
dV = V - (double)DirPatch( CouplerN, CNext ) * Couplers[ CouplerN ].Connected->V;
absdV = abs( dV );
// potentially generate sounds on clash or stretch
if( ( newdist < 0.0 )
&& ( Couplers[ CouplerN ].Dist > newdist )
if( ( newdistance < 0.0 )
&& ( coupler.Dist > newdistance )
&& ( dV < -0.5 ) ) {
// 090503: dzwieki pracy zderzakow
SetFlag(
Couplers[ CouplerN ].sounds,
coupler.sounds,
( absdV > 5.0 ?
( sound::bufferclash | sound::loud ) :
sound::bufferclash ) );
}
else if( ( Couplers[ CouplerN ].CouplingFlag != coupling::faux )
&& ( newdist > 0.001 )
&& ( Couplers[ CouplerN ].Dist <= 0.001 )
else if( ( coupler.CouplingFlag != coupling::faux )
&& ( newdistance > 0.001 )
&& ( coupler.Dist <= 0.001 )
&& ( absdV > 0.005 )
&& ( Vel > 1.0 ) ) {
// 090503: dzwieki pracy sprzegu
SetFlag(
Couplers[ CouplerN ].sounds,
coupler.sounds,
( absdV > 0.035 ?
( sound::couplerstretch | sound::loud ) :
sound::couplerstretch ) );
}
// blablabla
// ABu: proby znalezienia problemu ze zle odbijajacymi sie skladami
//if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (newdist>0) then
if( ( Couplers[ CouplerN ].CouplingFlag != coupling::faux )
|| ( Couplers[ CouplerN ].CoupleDist < 0 ) ) {
coupler.CheckCollision = false;
double CF { 0.0 };
if( Couplers[ CouplerN ].CouplingFlag == coupling::faux ) {
if( ( coupler.CouplingFlag != coupling::faux )
|| ( initialdistance < 0 ) ) {
BetaAvg = Couplers[CouplerN].beta;
Fmax = (Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB) * CouplerTune;
double BetaAvg = 0;
double Fmax = 0;
if( coupler.CouplingFlag == coupling::faux ) {
BetaAvg = coupler.beta;
Fmax = (coupler.FmaxC + coupler.FmaxB) * CouplerTune;
}
else // usrednij bo wspolny sprzeg
{
BetaAvg =
(Couplers[CouplerN].beta + Couplers[CouplerN].Connected->Couplers[CNext].beta) /
2.0;
Fmax = (Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB +
Couplers[CouplerN].Connected->Couplers[CNext].FmaxC +
Couplers[CouplerN].Connected->Couplers[CNext].FmaxB) *
CouplerTune / 2.0;
else {
// usrednij bo wspolny sprzeg
BetaAvg = 0.5 * ( coupler.beta + othercoupler.beta );
Fmax = 0.5 * ( coupler.FmaxC + coupler.FmaxB + othercoupler.FmaxC + othercoupler.FmaxB ) * CouplerTune;
}
distDelta =
abs(newdist) - abs(Couplers[CouplerN].Dist); // McZapkie-191103: poprawka na histereze
Couplers[CouplerN].Dist = newdist;
if (Couplers[CouplerN].Dist > 0)
{
if (distDelta > 0)
CF = (-(Couplers[CouplerN].SpringKC +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKC) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) -
Fmax * dV * BetaAvg;
else
CF = (-(Couplers[CouplerN].SpringKC +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKC) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) * BetaAvg -
Fmax * dV * BetaAvg;
auto const distDelta { std::abs( newdistance ) - std::abs( coupler.Dist ) }; // McZapkie-191103: poprawka na histereze
coupler.Dist = newdistance;
if (coupler.Dist > 0) {
if( distDelta > 0 ) {
CF = ( -( coupler.SpringKC + othercoupler.SpringKC ) * coupler.Dist / 2.0 ) * DirF( End )
- Fmax * dV * BetaAvg;
}
else {
CF = ( -( coupler.SpringKC + othercoupler.SpringKC ) * coupler.Dist / 2.0 ) * DirF( End ) * BetaAvg
- Fmax * dV * BetaAvg;
}
// liczenie sily ze sprezystosci sprzegu
if (Couplers[CouplerN].Dist >
(Couplers[CouplerN].DmaxC +
Couplers[CouplerN].Connected->Couplers[CNext].DmaxC)) // zderzenie
//***if tempdist>(DmaxC+Connected^.Couplers[CNext].DmaxC) then {zderzenie}
Couplers[CouplerN].CheckCollision = true;
if( coupler.Dist > ( coupler.DmaxC + othercoupler.DmaxC ) ) {
// zderzenie
coupler.CheckCollision = true;
}
}
if (Couplers[CouplerN].Dist < 0)
{
if (distDelta > 0)
CF = (-(Couplers[CouplerN].SpringKB +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKB) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) -
Fmax * dV * BetaAvg;
else
CF = (-(Couplers[CouplerN].SpringKB +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKB) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) * BetaAvg -
Fmax * dV * BetaAvg;
if( coupler.Dist < 0 ) {
if( distDelta > 0 ) {
CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End )
- Fmax * dV * BetaAvg;
}
else {
CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End ) * BetaAvg
- Fmax * dV * BetaAvg;
}
// liczenie sily ze sprezystosci zderzaka
if (-Couplers[CouplerN].Dist >
(Couplers[CouplerN].DmaxB +
Couplers[CouplerN].Connected->Couplers[CNext].DmaxB)) // zderzenie
//***if -tempdist>(DmaxB+Connected^.Couplers[CNext].DmaxB)/10 then {zderzenie}
{
Couplers[CouplerN].CheckCollision = true;
if( ( Couplers[ CouplerN ].CouplerType == TCouplerType::Automatic )
&& ( Couplers[ CouplerN ].CouplingFlag == coupling::faux ) ) {
// sprzeganie wagonow z samoczynnymi sprzegami}
// CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll+ctrain_passenger+ctrain_scndpneumatic;
if( -coupler.Dist > ( coupler.DmaxB + othercoupler.DmaxB ) ) {
// zderzenie
coupler.CheckCollision = true;
if( ( coupler.CouplerType == TCouplerType::Automatic )
&& ( coupler.CouplingFlag == coupling::faux ) ) {
// sprzeganie wagonow z samoczynnymi sprzegami
// EN57
Couplers[ CouplerN ].CouplingFlag = coupling::coupler /*| coupling::brakehose | coupling::mainhose | coupling::control*/;
SetFlag( Couplers[ CouplerN ].sounds, sound::attachcoupler );
// TBD, TODO: configurable flag for automatic coupling
coupler.CouplingFlag = coupling::coupler /*| coupling::brakehose | coupling::mainhose | coupling::control*/;
SetFlag( coupler.sounds, sound::attachcoupler );
}
}
}
}
if( Couplers[ CouplerN ].CouplingFlag != coupling::faux ) {
if( coupler.CouplingFlag != coupling::faux ) {
// uzgadnianie prawa Newtona
Couplers[ CouplerN ].Connected->Couplers[ 1 - CouplerN ].CForce = -CF;
othervehicle->Couplers[ 1 - End ].CForce = -CF;
}
return CF;
@@ -5314,7 +5207,7 @@ double TMoverParameters::TractionForce( double dt ) {
// Q: 20160713
//Obliczenie predkości obrotowej kół???
// *************************************************************************************************
double TMoverParameters::ComputeRotatingWheel(double WForce, double dt, double n)
double TMoverParameters::ComputeRotatingWheel(double WForce, double dt, double n) const
{
double newn = 0, eps = 0;
if ((n == 0) && (WForce * Sign(V) < 0))
@@ -7150,17 +7043,16 @@ double TMoverParameters::GetTrainsetVoltage(void)
// *************************************************************************************************
// Kasowanie zmiennych pracy fizyki
// *************************************************************************************************
bool TMoverParameters::Physic_ReActivation(void) // DO PRZETLUMACZENIA NA KONCU
bool TMoverParameters::switch_physics(bool const State) // DO PRZETLUMACZENIA NA KONCU
{
// bool pr;
if (PhysicActivation)
return false;
else
{
PhysicActivation = true;
if( PhysicActivation == State ) { return false; }
PhysicActivation = State;
if( true == State ) {
LastSwitchingTime = 0;
return true;
}
return true;
}
// *************************************************************************************************
@@ -9970,8 +9862,7 @@ bool TMoverParameters::RunInternalCommand()
CommandIn.Location.X = 0;
CommandIn.Location.Y = 0;
CommandIn.Location.Z = 0;
if (!PhysicActivation)
Physic_ReActivation();
switch_physics( true );
}
}
else

View File

@@ -4867,11 +4867,11 @@ void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Comm
if( false == Train->CabChange( 1 ) ) {
if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ end::front ].CouplingFlag, coupling::gangway ) ) {
// przejscie do nastepnego pojazdu
Global.changeDynObj = Train->DynamicObject->PrevConnected;
Global.changeDynObj = Train->DynamicObject->PrevConnected();
Global.changeDynObj->MoverParameters->ActiveCab = (
Train->DynamicObject->PrevConnectedNo ?
-1 :
1 );
Train->DynamicObject->MoverParameters->Neighbours[end::front].vehicle_end ?
-1 :
1 );
}
}
}
@@ -4883,11 +4883,11 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com
if( false == Train->CabChange( -1 ) ) {
if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ end::rear ].CouplingFlag, coupling::gangway ) ) {
// przejscie do nastepnego pojazdu
Global.changeDynObj = Train->DynamicObject->NextConnected;
Global.changeDynObj = Train->DynamicObject->NextConnected();
Global.changeDynObj->MoverParameters->ActiveCab = (
Train->DynamicObject->NextConnectedNo ?
-1 :
1 );
Train->DynamicObject->MoverParameters->Neighbours[end::rear].vehicle_end ?
-1 :
1 );
}
}
}
@@ -5260,14 +5260,14 @@ bool TTrain::Update( double const Deltatime )
{
TDynamicObject *tmp;
tmp = NULL;
if (DynamicObject->NextConnected)
if (DynamicObject->NextConnected())
if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab == 1))
tmp = DynamicObject->NextConnected;
if (DynamicObject->PrevConnected)
tmp = DynamicObject->NextConnected();
if (DynamicObject->PrevConnected())
if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab == -1))
tmp = DynamicObject->PrevConnected;
tmp = DynamicObject->PrevConnected();
if( tmp ) {
if( tmp->MoverParameters->Power > 0 ) {
if( ggI1B.SubModel ) {
@@ -5668,10 +5668,10 @@ bool TTrain::Update( double const Deltatime )
tmp = NULL;
if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab > 0))
tmp = DynamicObject->NextConnected;
tmp = DynamicObject->NextConnected();
if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab < 0))
tmp = DynamicObject->PrevConnected;
tmp = DynamicObject->PrevConnected();
if (tmp)
if ( mvControlled->Battery || mvControlled->ConverterFlag ) {
@@ -6954,26 +6954,25 @@ void TTrain::DynamicSet(TDynamicObject *d)
mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT
if (!DynamicObject)
return;
if (mvControlled->TrainType & dt_EZT) // na razie dotyczy to EZT
if (DynamicObject->NextConnected ? mvControlled->Couplers[1].AllowedFlag & ctrain_depot :
false)
{ // gdy jest człon od sprzęgu 1, a sprzęg łączony
// warsztatowo (powiedzmy)
if ((mvControlled->Power < 1.0) && (mvControlled->Couplers[1].Connected->Power >
1.0)) // my nie mamy mocy, ale ten drugi ma
mvControlled =
DynamicObject->NextConnected->MoverParameters; // będziemy sterować tym z mocą
// TODO: leverage code already present in TDynamicObject::ControlledFind()
if( ( d->MoverParameters->TrainType == dt_EZT )
|| ( d->MoverParameters->TrainType == dt_DMU ) ) {
if( ( d->NextConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
else if (DynamicObject->PrevConnected ?
mvControlled->Couplers[0].AllowedFlag & ctrain_depot :
false)
{ // gdy jest człon od sprzęgu 0, a sprzęg łączony
// warsztatowo (powiedzmy)
if ((mvControlled->Power < 1.0) && (mvControlled->Couplers[0].Connected->Power >
1.0)) // my nie mamy mocy, ale ten drugi ma
mvControlled =
DynamicObject->PrevConnected->MoverParameters; // będziemy sterować tym z mocą
else if( ( d->PrevConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
}
mvSecond = NULL; // gdyby się nic nie znalazło
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
if (mvOccupied->Couplers[1].Connected ?

View File

@@ -218,8 +218,7 @@ timetable_panel::update() {
auto consistmass { owner->fMass };
auto consistlength { owner->fLength };
if( ( owner->mvControlling->TrainType != dt_DMU )
&& ( owner->mvControlling->TrainType != dt_EZT )
&& ( owner->pVehicles[end::front] != owner->pVehicles[end::rear] ) ) {
&& ( owner->mvControlling->TrainType != dt_EZT ) ) {
//odejmij lokomotywy czynne, a przynajmniej aktualną
consistmass -= owner->pVehicle->MoverParameters->TotalMass;
// subtract potential other half of a two-part vehicle
@@ -227,7 +226,6 @@ timetable_panel::update() {
if( previous != nullptr ) { consistmass -= previous->MoverParameters->TotalMass; }
auto const *next { owner->pVehicle->NextC( coupling::permanent ) };
if( next != nullptr ) { consistmass -= next->MoverParameters->TotalMass; }
// consistlength -= owner->pVehicle->MoverParameters->Dim.L;
}
std::snprintf(
m_buffer.data(), m_buffer.size(),
@@ -563,10 +561,7 @@ debug_panel::update_vehicle_coupler( int const Side ) {
// NOTE: mover and vehicle are guaranteed to be valid by the caller
std::string couplerstatus { locale::strings[ locale::string::debug_vehicle_none ] };
auto const *connected { (
Side == end::front ?
m_input.vehicle->PrevConnected :
m_input.vehicle->NextConnected ) };
auto const *connected { m_input.vehicle->MoverParameters->Neighbours[ Side ].vehicle };
if( connected == nullptr ) { return couplerstatus; }
@@ -574,10 +569,10 @@ debug_panel::update_vehicle_coupler( int const Side ) {
std::snprintf(
m_buffer.data(), m_buffer.size(),
"%s [%d]%s",
"%s [%d] (%.1f m)",
connected->name().c_str(),
mover.Couplers[ Side ].CouplingFlag,
std::string( mover.Couplers[ Side ].CouplingFlag == 0 ? " (" + to_string( mover.Couplers[ Side ].CoupleDist, 1 ) + " m)" : "" ).c_str() );
mover.Neighbours[ Side ].distance );
return { m_buffer.data() };
}
@@ -700,6 +695,10 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
"Distances:\n proximity: " + to_string( mechanik.ActualProximityDist, 0 )
+ ", braking: " + to_string( mechanik.fBrakeDist, 0 );
if( mechanik.Obstacle.distance < 5000 ) {
textline += "\n obstacle: " + to_string( mechanik.Obstacle.distance, 0 );
}
Output.emplace_back( textline, Global.UITextColor );
// velocity factors