18
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-15 00:15:15 +01:00

Merge pull request #281 from MaSzyna-EU07/feat/shunt-pantograph-config

AI: suggested pantograph setup for shunting in the .fiz (eu07/maszyna#461)
This commit is contained in:
2026-11-09 12:52:58 +00:00
committed by GitHub
5 changed files with 79 additions and 1 deletions

View File

@@ -2352,6 +2352,9 @@ class TMoverParameters
plc::basic_controller m_plc;
int AIHintPantstate{0}; // suggested pantograph setup
// suggested pantograph setup in shunting (AI: ShuntPantstate=, eu07/maszyna#461), the bits as in Pantstate: 1 front,
// 2 rear, 3 both; 0 (the default) shunts with the pantographs handled as in train mode
int AIHintShuntPantstate{0};
bool AIHintPantUpIfIdle{true}; // whether raise both pantographs if idling for a while
double AIHintLocalBrakeAccFactor{1.05}; // suggested acceleration weight for local brake operation

View File

@@ -11616,6 +11616,7 @@ void TMoverParameters::LoadFIZ_AI(std::string const &Input)
{
extract_value(AIHintPantstate, "Pantstate", Input, "");
extract_value(AIHintShuntPantstate, "ShuntPantstate", Input, "");
extract_value(AIHintPantUpIfIdle, "IdlePantUp", Input, "");
extract_value(AIHintLocalBrakeAccFactor, "LocalBrakeAccFactor", Input, "");
}

View File

@@ -0,0 +1,31 @@
#include "stdafx.h"
#include "doctest.h"
#include "vehicle.h"
using test::definition;
using test::vehicle;
// the hints for the AI driver from the AI section of the .fiz
TEST_CASE("ai hints: without the AI section the pantographs follow the built-in logic") {
vehicle wagon{definition::load("wagon")};
CHECK(wagon->AIHintPantstate == 0);
CHECK(wagon->AIHintShuntPantstate == 0);
CHECK(wagon->AIHintPantUpIfIdle);
}
TEST_CASE("ai hints: the suggested pantograph setup for shunting is read apart from the one for train mode") {
// eu07/maszyna#461: so the ET41 doesn't shunt with all of its four pantographs up
vehicle shunting{definition::load("wagon").set("AI", "Pantstate", 1).set("AI", "ShuntPantstate", 2)};
CHECK(shunting->AIHintPantstate == 1);
CHECK(shunting->AIHintShuntPantstate == 2);
}
TEST_CASE("ai hints: a .fiz with the setup for train mode only has none for shunting") {
vehicle train{definition::load("wagon").set("AI", "Pantstate", 3)};
CHECK(train->AIHintPantstate == 3);
CHECK(train->AIHintShuntPantstate == 0);
}

View File

@@ -6229,6 +6229,13 @@ TController::control_pantographs() {
fActionTime = -2.0 - Random(10);
}
// the pantograph setup the .fiz suggests for shunting (AI: ShuntPantstate=, eu07/maszyna#461), 0 when there's none
// or the vehicle isn't shunting
auto const shuntpantographsetup {
( OrderCurrentGet() & ( Shunt | Loose_shunt ) ) != 0 ?
mvOccupied->AIHintShuntPantstate :
0 };
// raise/lower pantographs as needed
auto const useregularpantographlayout {
pVehicle->Next(coupling::control) == nullptr // standalone
@@ -6255,7 +6262,11 @@ TController::control_pantographs() {
// jeśli nie trzeba opuszczać pantografów
// TODO: check if faction alone reduces frequency enough
if( fActionTime > 0.0 ) {
if( mvOccupied->AIHintPantstate == 0 ) {
if( shuntpantographsetup != 0 ) {
// shunting with the pantograph setup the .fiz suggests for it
control_pantographs_setup( shuntpantographsetup );
}
else if( mvOccupied->AIHintPantstate == 0 ) {
// jazda na tylnym
if( iDirection >= 0 && useregularpantographlayout ) {
// jak jedzie w kierunku sprzęgu 0
@@ -6308,6 +6319,12 @@ TController::control_pantographs() {
}
}
}
else if( shuntpantographsetup != 0 ) {
// shunting with the suggested setup, also while standing, and without raising more pantographs when idling
if( fOverhead2 <= 0.0 && iOverheadDown == 0 ) {
control_pantographs_setup( shuntpantographsetup );
}
}
else {
if( !mvOccupied->AIHintPantUpIfIdle || IdleTime <= 45.0 || std::abs(fStopTime) <= 15.0 || mvPantographUnit->EnginePowerSource.CollectorParameters.CollectorsNo <= 1 )
{
@@ -6334,6 +6351,31 @@ TController::control_pantographs() {
}
}
// raises the pantographs of the suggested setup (bit 0: front, bit 1: rear) and lowers the others, these only once
// a pantograph of the setup collects the voltage, so the vehicle doesn't lose its power on the way
void
TController::control_pantographs_setup( int const Setup ) {
auto const front { ( Setup & 1 << 0 ) != 0 };
auto const rear { ( Setup & 1 << 1 ) != 0 };
if( front ) {
cue_action( driver_hint::frontpantographvalveon );
}
if( rear ) {
cue_action( driver_hint::rearpantographvalveon );
}
if( auto const setuplive { ( front && mvPantographUnit->PantFrontVolt != 0.0 ) || ( rear && mvPantographUnit->PantRearVolt != 0.0 ) };
false == setuplive ) {
return;
}
if( false == front ) {
cue_action( driver_hint::frontpantographvalveoff );
}
if( false == rear ) {
cue_action( driver_hint::rearpantographvalveoff );
}
}
void
TController::control_horns( double const Timedelta ) {
// horn control

View File

@@ -323,6 +323,7 @@ private:
void scan_obstacles( double const Range );
void control_wheelslip();
void control_pantographs();
void control_pantographs_setup( int const Setup );
void control_horns( double const Timedelta );
void control_security_system( double const Timedelta );
void control_handles();