diff --git a/Trigger/TrigEvent/TrigNavTools/CMakeLists.txt b/Trigger/TrigEvent/TrigNavTools/CMakeLists.txt
index d9c1693d63f7ee3853e9b0a91a12f9164c594a04..2147e424b8b16761237dd5d9af78181810d4cf8e 100644
--- a/Trigger/TrigEvent/TrigNavTools/CMakeLists.txt
+++ b/Trigger/TrigEvent/TrigNavTools/CMakeLists.txt
@@ -17,4 +17,5 @@ atlas_add_component( TrigNavTools
 # Install files from the package:
 atlas_install_python_modules( python/__init__.py python/TrigNavToolsConfig.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
 atlas_install_joboptions( share/*.py )
+atlas_install_scripts( share/RunNavDump.py )
 
diff --git a/Trigger/TrigEvent/TrigNavTools/share/RunNavDump.py b/Trigger/TrigEvent/TrigNavTools/share/RunNavDump.py
new file mode 100755
index 0000000000000000000000000000000000000000..ebd811ec8d83fe42ae0dbd8eba590f2009b3edb4
--- /dev/null
+++ b/Trigger/TrigEvent/TrigNavTools/share/RunNavDump.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+#  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+#
+
+if __name__=='__main__':
+    import sys
+
+    # Setup the Run III behavior
+    from AthenaCommon.Configurable import Configurable
+    Configurable.configurableRun3Behavior = 1
+
+    # Set the Athena configuration flags
+    from AthenaConfiguration.AllConfigFlags import ConfigFlags
+    parser = ConfigFlags.getArgumentParser()
+    args = parser.parse_args()
+
+    #test input file: --filesInput='/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/Tier0ChainTests/q221/21.0/myAOD.pool.root'
+
+    # Set the Athena configuration flags
+    ConfigFlags.fillFromArgs()
+    ConfigFlags.Output.AODFileName = "outAOD.pool.root"
+    ConfigFlags.Detector.GeometryLAr=True
+    ConfigFlags.Detector.GeometryTile=True
+    ConfigFlags.lock()
+
+    # Initialize configuration object, add accumulator, merge, and run.
+    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+    from AthenaConfiguration.ComponentFactory import CompFactory
+
+    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+    cfg = MainServicesCfg(ConfigFlags)
+    cfg.merge(PoolReadCfg(ConfigFlags))
+
+
+    from AthenaServices.MetaDataSvcConfig import MetaDataSvcCfg
+    cfg.merge(MetaDataSvcCfg(ConfigFlags))
+
+    confSvc = CompFactory.TrigConf.xAODConfigSvc("HLTConfigSvc")
+    cfg.addService(confSvc)
+    from AthenaCommon.Constants import DEBUG
+    alg = CompFactory.Run2ToRun3TrigNavConverter("TrigNavCnv", OutputLevel=DEBUG, HLTConfigSvc=confSvc)
+    alg.doPrint = False
+    alg.setConfig = ["xAOD::ElectronContainer","xAOD::TrigEMClusterContainer","xAOD::TrigEMCluster","xAOD::TrigElectron","xAOD::TrigElectronContainer","TrigRoiDescriptor","TrigRoiDescriptorCollection"]
+    cfg.addEventAlgo(alg, sequenceName="AthAlgSeq")
+
+
+    from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+    outputType="AOD"
+    toRecord = ["xAOD::TrigCompositeContainer#HLTNav_all", "xAOD::TrigCompositeAuxContainer#HLTNav_allAux.",
+                "xAOD::TrigCompositeContainer#HLTNav_Summary", "xAOD::TrigCompositeAuxContainer#HLTNav_SummaryAux."]
+    outputCfg = OutputStreamCfg(ConfigFlags, outputType, ItemList=toRecord, disableEventTag=True)
+    streamAlg = outputCfg.getEventAlgo("OutputStream"+outputType)
+    # need to expand possble options for the OutputStreamCfg to be able to pass also the metadata containers
+    streamAlg.MetadataItemList += ["xAOD::TriggerMenuContainer#TriggerMenu", "xAOD::TriggerMenuAuxContainer#TriggerMenuAux."]
+    streamAlg.TakeItemsFromInput = True
+    cfg.addPublicTool(CompFactory.xAODMaker.TriggerMenuMetaDataTool("TriggerMenuMetaDataTool"))
+    cfg.addService( CompFactory.MetaDataSvc("MetaDataSvc", MetaDataTools = [cfg.getPublicTool("TriggerMenuMetaDataTool")]))
+
+    cfg.merge(outputCfg)
+
+    # input EDM needs calo det descrition for conversion (uff)
+    from LArGeoAlgsNV.LArGMConfig import LArGMCfg
+    from TileGeoModel.TileGMConfig import TileGMCfg
+    cfg.merge(LArGMCfg(ConfigFlags))
+    cfg.merge(TileGMCfg(ConfigFlags))
+
+    cfg.printConfig(withDetails=True, summariseProps=False) # set True for exhaustive info
+    sc = cfg.run(args.evtMax, args.loglevel)
+    sys.exit(0 if sc.isSuccess() else 1)
diff --git a/Trigger/TrigEvent/TrigNavTools/src/Run2ToRun3TrigNavConverter.cxx b/Trigger/TrigEvent/TrigNavTools/src/Run2ToRun3TrigNavConverter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..339c85b99b8b4b3920255a51313829a09154b4ab
--- /dev/null
+++ b/Trigger/TrigEvent/TrigNavTools/src/Run2ToRun3TrigNavConverter.cxx
@@ -0,0 +1,194 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Run2ToRun3TrigNavConverter.h"
+//#include "TrigNavStructure/StandaloneNavigation.h"
+#include "TrigConfHLTData/HLTChainList.h"
+#include "TrigConfHLTData/HLTSignature.h"
+#include "TrigConfHLTData/HLTTriggerElement.h"
+#include "TrigNavStructure/TriggerElement.h"
+
+
+Run2ToRun3TrigNavConverter::Run2ToRun3TrigNavConverter(const std::string& name, ISvcLocator* pSvcLocator) :
+  AthReentrantAlgorithm(name, pSvcLocator)
+{
+}
+
+Run2ToRun3TrigNavConverter::~Run2ToRun3TrigNavConverter()
+{
+}
+
+StatusCode Run2ToRun3TrigNavConverter::initialize()
+{
+
+  ATH_CHECK( m_trigNavKey.initialize() );
+  ATH_CHECK( m_trigNavWriteKey.initialize() );
+  ATH_CHECK( m_trigSummaryWriteKey.initialize() );
+  ATH_CHECK( m_configSvc.retrieve() );
+  ATH_CHECK( m_clidSvc.retrieve() );
+
+  // retrievig CLID from names and storing to set
+  for (const auto& name : m_setConfig) {
+    CLID id {0};
+    ATH_CHECK( m_clidSvc->getIDOfTypeName(name, id) );
+    ATH_MSG_DEBUG("CLID NAME: " << name << " ID: " << id);
+    m_setCLID.insert(id);
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode Run2ToRun3TrigNavConverter::finalize()
+{
+  return StatusCode::SUCCESS;
+}
+
+StatusCode Run2ToRun3TrigNavConverter::execute(const EventContext& context) const
+{
+  SG::ReadHandle navReadHandle(m_trigNavKey, context);
+
+  ATH_CHECK( navReadHandle.isValid() );
+
+  HLT::StandaloneNavigation navDecoder = HLT::StandaloneNavigation();
+  
+  navDecoder.deserialize( navReadHandle->serialized() );
+
+  SG::WriteHandle< TrigCompositeUtils::DecisionContainer > outputNavigation = TrigCompositeUtils::createAndStore( m_trigNavWriteKey, context );
+  auto decisionOutput = outputNavigation.ptr();
+  SG::WriteHandle< TrigCompositeUtils::DecisionContainer > outputSummary = TrigCompositeUtils::createAndStore( m_trigSummaryWriteKey, context );
+  auto decisionSummary = outputSummary.ptr();
+  TrigCompositeUtils::Decision* passRawOutput = TrigCompositeUtils::newDecisionIn( decisionSummary, "HLTPassRaw" );
+
+
+    if (m_doPrint) {
+      std::string dump;
+      navDecoder.printASCIIArt(dump);
+      ATH_MSG_INFO(dump);
+    }
+
+    // example chains used for testing
+    const std::string chainName{"HLT_e26_lhtight_nod0"};
+    //const std::string chainName{"HLT_e28_lhtight_nod0"};
+
+    std::vector<HLT::TriggerElement*> tes;
+    TE_Decision_map mapTEtoDecision; // TE - Decision (xAOD::TrigComposite)   
+    TE_Decision_map mapTEtoDecisionActive; // TE Active - Decision (xAOD::TrigComposite)   
+    std::vector<TrigCompositeUtils::Decision*> decisionLast; // storing "last" decision in a chain
+
+    std::vector<HLT::TriggerElement::FeatureAccessHelper> featureRoI; // for keeping predecessing TE with RoI
+
+
+    auto c = m_configSvc->chains().chain(chainName);
+    // create HLT Identifier aka decision ID
+    HLT::Identifier chainId = HLT::Identifier(chainName);
+
+
+    TrigCompositeUtils::Decision *passActive = TrigCompositeUtils::newDecisionIn(decisionOutput, "HLTActive");
+
+    ATH_MSG_DEBUG("CHAIN SIZE [signatures]: " << c->signatures().size());
+    //for (auto s : c->signatures()) {
+    for (auto s_iter = c->signatures().begin(), first_s_iter = s_iter; s_iter != c->signatures().end();  ++s_iter) {
+      for (auto te : (*s_iter)->outputTEs()) {
+        tes.clear();
+        decisionLast.clear();
+        navDecoder.getAllOfType(te->id(), tes, false);
+        
+        for (auto teptr : tes) {
+
+          for ( auto elemFE : vectorTEfeatures( teptr ) ) {
+            auto decision = TrigCompositeUtils::newDecisionIn(decisionOutput);
+            mapTEtoDecision[teptr].push_back( decision );  
+            if (teptr->getActiveState())
+            {
+              auto decisionFeature = TrigCompositeUtils::newDecisionIn(decisionOutput);
+              TrigCompositeUtils::linkToPrevious(decisionFeature, decision, context);
+              mapTEtoDecisionActive[teptr].push_back( decisionFeature );
+              ATH_CHECK(addTEfeatures( navDecoder, elemFE, decisionFeature ));
+              if (s_iter == first_s_iter)
+              {
+                for ( const auto& rNodes : HLT::TrigNavStructure::getRoINodes( teptr ) ) {
+                  if ( HLT::TrigNavStructure::isRoINode(rNodes) ) {
+                    for ( auto featureRoI : vectorTEfeatures( rNodes ) ) { 
+                      ATH_CHECK(addTEfeatures( navDecoder, featureRoI, decisionFeature, true ));
+                    }
+                  }
+                }
+              }
+              TrigCompositeUtils::addDecisionID(chainId, decisionFeature);
+              decisionLast.push_back( decisionFeature );
+            }
+          }
+
+         
+          for ( auto prep_ptr : navDecoder.getDirectPredecessors(teptr) ) {
+            if (mapTEtoDecision.find(prep_ptr) != mapTEtoDecision.end())
+            {
+              for (auto d : mapTEtoDecision[teptr])
+              {
+                for (auto pd : mapTEtoDecision[prep_ptr])
+                {
+                  TrigCompositeUtils::linkToPrevious(d, pd, context);
+                  ATH_MSG_DEBUG("decision - previous decision");
+                }
+              }
+              for (auto d : mapTEtoDecisionActive[teptr])
+              {
+                for (auto pd : mapTEtoDecisionActive[prep_ptr])
+                {
+                  TrigCompositeUtils::linkToPrevious(d, pd, context);
+                  ATH_MSG_DEBUG("ACTIVE decision - previous decision");
+                }
+              }
+            }
+          }
+
+        }
+      }
+    }
+    for ( auto last: decisionLast ) {
+      TrigCompositeUtils::Decision* filter = TrigCompositeUtils::newDecisionIn( decisionSummary, passActive, "F", context );
+      TrigCompositeUtils::linkToPrevious(filter, last, context);
+      TrigCompositeUtils::decisionIDs(filter).push_back(chainId);
+      TrigCompositeUtils::linkToPrevious( passRawOutput, filter, context );
+    }
+    TrigCompositeUtils::decisionIDs( passRawOutput ).push_back(chainId);
+
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode Run2ToRun3TrigNavConverter::addTEfeatures(const HLT::StandaloneNavigation &navigationDecoder, HLT::TriggerElement::FeatureAccessHelper helper, TrigCompositeUtils::Decision *decisionPtr, bool kRoI) const
+{
+    std::string sgKeyString = navigationDecoder.label(helper.getCLID(), helper.getIndex().subTypeIndex());
+    std::string type_name;
+    ATH_CHECK(m_clidSvc->getTypeNameOfID(helper.getCLID(), type_name));
+    ATH_MSG_DEBUG("----------------Attached collection " << sgKeyString << ", " << helper << " NAME: " << type_name);
+
+    ATH_MSG_DEBUG(" SG KEY NAME from formatSGkey: " << HLTNavDetails::formatSGkey("HLT", type_name, sgKeyString));
+
+    auto sgKey = evtStore()->stringToKey(HLTNavDetails::formatSGkey("HLT", type_name, sgKeyString), helper.getCLID());
+    const CLID saveCLID =  (helper.getCLID() == 6455 ? 1097199488 : helper.getCLID());
+
+    if ( kRoI ) {
+      decisionPtr->typelessSetObjectLink(TrigCompositeUtils::roiString(), sgKey, saveCLID, helper.getIndex().objectsBegin());
+    } else {
+      decisionPtr->typelessSetObjectLink(TrigCompositeUtils::featureString(), sgKey, helper.getCLID(), helper.getIndex().objectsBegin(), helper.getIndex().objectsEnd());
+    }
+  
+  return StatusCode::SUCCESS;
+}
+
+const std::vector<HLT::TriggerElement::FeatureAccessHelper> Run2ToRun3TrigNavConverter::vectorTEfeatures(const HLT::TriggerElement *te_ptr) const
+{
+  std::vector<HLT::TriggerElement::FeatureAccessHelper> ptrFAHelper; 
+  for (HLT::TriggerElement::FeatureAccessHelper helper : te_ptr->getFeatureAccessHelpers())
+  {
+       if (m_setCLID.find(helper.getCLID()) == m_setCLID.end()) {
+         continue;
+       }
+      ptrFAHelper.push_back( helper );
+  }
+  ATH_MSG_DEBUG(" **************** SIZE OF TCs: " << ptrFAHelper.size());
+  return ptrFAHelper;
+}
diff --git a/Trigger/TrigEvent/TrigNavTools/src/Run2ToRun3TrigNavConverter.h b/Trigger/TrigEvent/TrigNavTools/src/Run2ToRun3TrigNavConverter.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b28867b508012769556690333356d167eab7a65
--- /dev/null
+++ b/Trigger/TrigEvent/TrigNavTools/src/Run2ToRun3TrigNavConverter.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef TRIGNAVTOOLS_RUN2TORUN3TRIGNAVCONVERTER_H
+#define TRIGNAVTOOLS_RUN2TORUN3TRIGNAVCONVERTER_H
+
+// Framework includes
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "xAODTrigger/TrigNavigation.h"
+#include "TrigConfInterfaces/IHLTConfigSvc.h"
+#include "AthenaKernel/IClassIDSvc.h"
+#include "xAODTrigger/TrigComposite.h"
+#include "xAODTrigger/TrigCompositeContainer.h"
+#include "TrigCompositeUtils/TrigCompositeUtils.h"
+#include "TrigNavStructure/TypedHolder.h"
+#include "TrigNavStructure/StandaloneNavigation.h"
+
+// STL includes
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+
+/**
+ * @class Run2ToRun3TrigNavConverter
+ * @brief 
+ **/
+class Run2ToRun3TrigNavConverter : public AthReentrantAlgorithm {
+public:
+  Run2ToRun3TrigNavConverter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~Run2ToRun3TrigNavConverter() override;
+
+  virtual StatusCode initialize() override;
+  virtual StatusCode execute(const EventContext& context) const override;
+  virtual StatusCode finalize() override;
+
+private:
+
+
+    SG::ReadHandleKey<xAOD::TrigNavigation> m_trigNavKey { this, "TrigNavReadKey", "TrigNavigation"};
+    Gaudi::Property<bool> m_doPrint{ this, "doPrint", true };
+    Gaudi::Property<std::vector<std::string>> m_setConfig{ this, "setConfig", {} };
+    ServiceHandle< TrigConf::IHLTConfigSvc > m_configSvc { this, "HLTConfigSvc", "HLTConfigSvc", "HLTConfig Service" };
+    ServiceHandle<IClassIDSvc> m_clidSvc{ this, "ClassIDSvc", "ClassIDSvc", "Service to translate CLID to class name" };
+    SG::WriteHandleKey<xAOD::TrigCompositeContainer> m_trigNavWriteKey { this, "TrigNavWriteKey", "HLTNav_all" };
+    SG::WriteHandleKey<xAOD::TrigCompositeContainer> m_trigSummaryWriteKey { this, "TrigSummaryWriteKey", "HLTNav_Summary" };
+
+    std::set<CLID> m_setCLID;
+    StatusCode addTEfeatures(const HLT::StandaloneNavigation &navigationDecoder, HLT::TriggerElement::FeatureAccessHelper helper, TrigCompositeUtils::Decision *decisionPtr, bool kRoI=false) const;
+    const std::vector<HLT::TriggerElement::FeatureAccessHelper> vectorTEfeatures(const HLT::TriggerElement *te_ptr) const;
+
+    using TE_Decision_map = std::map<HLT::TriggerElement*, std::vector<TrigCompositeUtils::Decision*>>;
+};
+
+#endif // TRIGNAVTOOLS_RUN2TORUN3TRIGNAVCONVERTER_H
diff --git a/Trigger/TrigEvent/TrigNavTools/src/components/TrigNavTools_entries.cxx b/Trigger/TrigEvent/TrigNavTools/src/components/TrigNavTools_entries.cxx
index 8dcfaf68c4b519df87e0faa7da60d111368f1f9c..e9cc2cb75271290fce640dc9e0f554427326c3d8 100644
--- a/Trigger/TrigEvent/TrigNavTools/src/components/TrigNavTools_entries.cxx
+++ b/Trigger/TrigEvent/TrigNavTools/src/components/TrigNavTools_entries.cxx
@@ -1,6 +1,8 @@
 
 #include "../TrigNavigationThinningSvc.h"
+#include "../Run2ToRun3TrigNavConverter.h"
 
 
 DECLARE_COMPONENT( TrigNavigationThinningSvc )
+DECLARE_COMPONENT( Run2ToRun3TrigNavConverter )