diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/CMakeLists.txt b/Trigger/TrigAlgorithms/TrigL2MuonSA/CMakeLists.txt
index e565d1558255b6e9adf2aab811dfd5bf93a377f2..4f206331aecbf43d7557a8707b5c2c719c8dffcd 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/CMakeLists.txt
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/CMakeLists.txt
@@ -14,7 +14,7 @@ atlas_add_library( TrigL2MuonSALib
                    src/*.cxx
                    PUBLIC_HEADERS TrigL2MuonSA
                    INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GSL_INCLUDE_DIRS} ${TDAQ-COMMON_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                   LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps AthenaMonitoringKernelLib ByteStreamCnvSvcBaseLib CscClusterizationLib GaudiKernel GeoPrimitives Identifier MdtCalibSvcLib MuonCablingData MuonCnvToolInterfacesLib MuonIdHelpersLib MuonPrepRawData MuonRDO MuonRecToolInterfaces MuonTGC_CablingLib RPC_CondCablingLib RegionSelectorLib StoreGateLib TrigInterfacesLib TrigMuonToolInterfaces TrigSteeringEvent TrigT1Interfaces TrigT1RPCRecRoiSvcLib TrigTimeAlgsLib xAODEventInfo xAODTrigMuon xAODTrigger
+                   LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps AthenaMonitoringKernelLib ByteStreamCnvSvcBaseLib CscClusterizationLib GaudiKernel GeoPrimitives Identifier MdtCalibSvcLib MuonCablingData MuonCnvToolInterfacesLib MuonIdHelpersLib MuonPrepRawData MuonRDO MuonRecToolInterfaces MuonTGC_CablingLib RPC_CondCablingLib RegionSelectorLib StoreGateLib TrigInterfacesLib TrigMuonToolInterfaces TrigSteeringEvent TrigT1Interfaces TrkExInterfaces TrigT1RPCRecRoiSvcLib TrigTimeAlgsLib xAODEventInfo xAODTrigMuon xAODTrigger xAODTracking
                    PRIVATE_LINK_LIBRARIES ${CLHEP_LIBRARIES} ${GSL_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} AthenaInterprocess CxxUtils EventInfo GeoModelUtilities MuonCalibEvent MuonReadoutGeometry PathResolver )
 
 atlas_add_component( TrigL2MuonSA
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/FtfRoadDefiner.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/FtfRoadDefiner.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ad29a201b78d0c2e411ac75148cbfa1c16752f2f
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/FtfRoadDefiner.cxx
@@ -0,0 +1,214 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FtfRoadDefiner.h"
+
+// #include "TrigSteeringEvent/TrigRoiDescriptor.h"
+
+TrigL2MuonSA::FtfRoadDefiner::FtfRoadDefiner(const std::string& type,
+                                             const std::string& name,
+                                             const IInterface*  parent):
+  AthAlgTool(type, name, parent)
+{
+}
+
+// --------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------
+
+StatusCode TrigL2MuonSA::FtfRoadDefiner::initialize()
+{
+
+  ATH_CHECK( m_extrapolator.retrieve() );
+
+  return StatusCode::SUCCESS;
+}
+
+// --------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------
+
+StatusCode TrigL2MuonSA::FtfRoadDefiner::defineRoad(const xAOD::TrackParticle* idtrack,
+						    TrigL2MuonSA::MuonRoad&    muonRoad)
+{
+  ATH_MSG_DEBUG("FtfRoadDefiner::defineRoad");
+
+  const int N_SECTOR = 2; // 0: normal, 1:overlap
+
+  double extFtfInnerEta=0.,  extFtfInnerZ=0.,  extFtfInnerR=0.,  extFtfInnerPhi=0.;
+  double extFtfMiddleEta=0., extFtfMiddleZ=0., extFtfMiddleR=0., extFtfMiddlePhi=0.;
+  double extFtfOuterEta=0.,  extFtfOuterZ=0.,  extFtfOuterR=0.,  extFtfOuterPhi=0.;
+
+  double aw_ftf[3]={0.,0.,0.};
+  double bw_ftf[3]={0.,0.,0.};
+
+  // Inner
+  const Trk::TrackParameters* extFtfInner = extTrack( idtrack, 5000., 6000., muonRoad.ext_ftf_flag[0][0]); //Large secotr
+  if( !extFtfInner ) {
+    ATH_MSG_DEBUG("extrapolated track parameters on BarrelInner is null");
+  } else {
+    extFtfInnerEta = extFtfInner->eta();
+    extFtfInnerPhi = extFtfInner->position().phi();
+    extFtfInnerZ = extFtfInner->position().z();
+    extFtfInnerR = sqrt((extFtfInner->position().x())*(extFtfInner->position().x()) + (extFtfInner->position().y())*(extFtfInner->position().y()));
+    ATH_MSG_DEBUG("extFtfInnerEta: " << extFtfInnerEta << ", extFtfInnerPhi: " << extFtfInnerPhi << ", extFtfInnerZ: " << extFtfInnerZ << ", extFtfInnerR: " << extFtfInnerR);
+    aw_ftf[0] = tan(2*atan(exp(-extFtfInnerEta)));
+    bw_ftf[0] = extFtfInnerR - (aw_ftf[0])*extFtfInnerZ;
+    muonRoad.r_ftf[0][0] = extFtfInnerR;
+    muonRoad.z_ftf[0][0] = extFtfInnerZ;
+  }
+
+  // Middle
+  const Trk::TrackParameters* extFtfMiddle = extTrack( idtrack , 8000., 9000., muonRoad.ext_ftf_flag[1][0]);
+  if( !extFtfMiddle ) {
+    ATH_MSG_DEBUG("extrapolated track parameters on BarrelMiddle is null");
+  } else {
+    extFtfMiddleEta = extFtfMiddle->eta();
+    extFtfMiddlePhi = extFtfMiddle->position().phi();
+    extFtfMiddleZ = extFtfMiddle->position().z();
+    extFtfMiddleR = sqrt((extFtfMiddle->position().x())*(extFtfMiddle->position().x()) + (extFtfMiddle->position().y())*(extFtfMiddle->position().y()));
+    ATH_MSG_DEBUG("extFtfMiddleEta: " << extFtfMiddleEta << ", extFtfMiddlePhi: " << extFtfMiddlePhi << ", extFtfMiddleZ: " << extFtfMiddleZ << ", extFtfMiddleR: " << extFtfMiddleR);
+    aw_ftf[1] = tan(2*atan(exp(-extFtfMiddleEta)));
+    bw_ftf[1] = extFtfMiddleR - (aw_ftf[1])*extFtfMiddleZ;
+    muonRoad.r_ftf[1][0] = extFtfMiddleR;
+    muonRoad.z_ftf[1][0] = extFtfMiddleZ;
+  }
+
+  // Outer
+  const Trk::TrackParameters* extFtfOuter = extTrack( idtrack , 10000., 12500., muonRoad.ext_ftf_flag[2][0]);
+  if( !extFtfOuter ) {
+    ATH_MSG_DEBUG("extrapolated track parameters on BarrelOuter is null");
+  } else {
+    extFtfOuterEta = extFtfOuter->eta();
+    extFtfOuterPhi = extFtfOuter->position().phi();
+    extFtfOuterZ = extFtfOuter->position().z();
+    extFtfOuterR = sqrt((extFtfOuter->position().x())*(extFtfOuter->position().x()) + (extFtfOuter->position().y())*(extFtfOuter->position().y()));
+    ATH_MSG_DEBUG("extFtfOuterEta: " << extFtfOuterEta << ", extFtfOuterPhi: " << extFtfOuterPhi << ", extFtfOuterZ: " << extFtfOuterZ << ", extFtfOuterR: " << extFtfOuterR);
+    aw_ftf[2] = tan(2*atan(exp(-extFtfOuterEta)));
+    bw_ftf[2] = extFtfOuterR - (aw_ftf[2])*extFtfOuterZ;
+    muonRoad.r_ftf[2][0] = extFtfOuterR;
+    muonRoad.z_ftf[2][0] = extFtfOuterZ;
+  }
+
+  muonRoad.extFtfMiddleEta = extFtfMiddleEta;
+  muonRoad.extFtfMiddlePhi = extFtfMiddlePhi;
+
+  for (int i_sector=0; i_sector<N_SECTOR; i_sector++) {
+    muonRoad.aw_ftf[0][i_sector]  = aw_ftf[0];
+    muonRoad.bw_ftf[0][i_sector]  = bw_ftf[0];
+    muonRoad.aw_ftf[1][i_sector]  = aw_ftf[1];
+    muonRoad.bw_ftf[1][i_sector]  = bw_ftf[1];
+    muonRoad.aw_ftf[2][i_sector]  = aw_ftf[2];
+    muonRoad.bw_ftf[2][i_sector]  = bw_ftf[2];
+    muonRoad.aw_ftf[3][i_sector]  = aw_ftf[0];
+    muonRoad.bw_ftf[3][i_sector]  = bw_ftf[0];
+    muonRoad.aw_ftf[4][i_sector]  = aw_ftf[1];
+    muonRoad.bw_ftf[4][i_sector]  = bw_ftf[1];
+    muonRoad.aw_ftf[5][i_sector]  = aw_ftf[2];
+    muonRoad.bw_ftf[5][i_sector]  = bw_ftf[2];
+    muonRoad.aw_ftf[6][i_sector]  = aw_ftf[0];
+    muonRoad.bw_ftf[6][i_sector]  = bw_ftf[0];
+    muonRoad.aw_ftf[7][i_sector]  = aw_ftf[0];
+    muonRoad.bw_ftf[7][i_sector]  = bw_ftf[0];
+    muonRoad.aw_ftf[8][i_sector]  = aw_ftf[0];
+    muonRoad.bw_ftf[8][i_sector]  = bw_ftf[0];
+    muonRoad.aw_ftf[9][i_sector]  = aw_ftf[1];//BME
+    muonRoad.bw_ftf[9][i_sector]  = bw_ftf[1];
+    muonRoad.aw_ftf[10][i_sector] = aw_ftf[1];//BMG
+    muonRoad.bw_ftf[10][i_sector] = bw_ftf[1];
+
+    muonRoad.eta_ftf[0][i_sector]  = extFtfInnerEta;
+    muonRoad.phi_ftf[0][i_sector]  = extFtfInnerPhi;
+    muonRoad.eta_ftf[1][i_sector]  = extFtfMiddleEta;
+    muonRoad.phi_ftf[1][i_sector]  = extFtfMiddlePhi;
+    muonRoad.eta_ftf[2][i_sector]  = extFtfOuterEta;
+    muonRoad.phi_ftf[2][i_sector]  = extFtfOuterPhi;
+    muonRoad.eta_ftf[3][i_sector]  = extFtfInnerEta;
+    muonRoad.phi_ftf[3][i_sector]  = extFtfInnerPhi;
+    muonRoad.eta_ftf[4][i_sector]  = extFtfMiddleEta;
+    muonRoad.phi_ftf[4][i_sector]  = extFtfMiddlePhi;
+    muonRoad.eta_ftf[5][i_sector]  = extFtfOuterEta;
+    muonRoad.phi_ftf[5][i_sector]  = extFtfOuterPhi;
+    muonRoad.eta_ftf[6][i_sector]  = extFtfInnerEta;
+    muonRoad.phi_ftf[6][i_sector]  = extFtfInnerPhi;
+    muonRoad.eta_ftf[7][i_sector]  = extFtfInnerEta;
+    muonRoad.phi_ftf[7][i_sector]  = extFtfInnerPhi;
+    muonRoad.eta_ftf[8][i_sector]  = extFtfInnerEta;
+    muonRoad.phi_ftf[8][i_sector]  = extFtfInnerPhi;
+    muonRoad.eta_ftf[9][i_sector]  = extFtfMiddleEta;//BME
+    muonRoad.phi_ftf[9][i_sector]  = extFtfMiddlePhi;
+    muonRoad.eta_ftf[10][i_sector] = extFtfMiddleEta;//BMG
+    muonRoad.phi_ftf[10][i_sector] = extFtfMiddlePhi;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// --------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------
+
+const Trk::TrackParameters* TrigL2MuonSA::FtfRoadDefiner::extTrack( const xAOD::TrackParticle* trk, const double R, const double halflength, int& extFlag ) {
+
+  const bool boundaryCheck = true;
+  bool bCylinder = false;
+  bool bDisk = false;
+
+  double Z = ( trk->eta()>0 )? halflength:-halflength;
+
+  // Cylinder
+  Trk::CylinderSurface* barrel = new Trk::CylinderSurface( R, Z );
+  const Trk::Surface* surface1 = barrel;
+  const Trk::TrackParameters* param1 = m_extrapolator->extrapolate(*trk, *surface1, Trk::anyDirection, boundaryCheck, Trk::muon);
+
+  // Disk
+  Transform3D* matrix = new Transform3D( Amg::Vector3D( 0.,0.,Z ) );
+
+  Trk::DiscSurface* disc = new Trk::DiscSurface( matrix, 0, R );
+  const Trk::Surface* surface2 = disc;
+  const Trk::TrackParameters* param2 = m_extrapolator->extrapolate(*trk, *surface2, Trk::anyDirection, boundaryCheck, Trk::muon);
+
+  ATH_MSG_DEBUG("R: " << R << ", Z: " << Z);
+  if( !param1 ) {
+    ATH_MSG_DEBUG("Cylinder -> extrapolated track parameters on Cylinder is null");
+  } else {
+    bCylinder = true;
+    double Rms = sqrt((param1->position().x())*(param1->position().x()) + (param1->position().y())*(param1->position().y()));
+    ATH_MSG_DEBUG("Cylinder -> eta: " << param1->eta() << ", phi: " << param1->position().phi() << ", Z: " << param1->position().z() << ", Rms: " << Rms);
+  }
+
+  if( !param2 ) {
+    ATH_MSG_DEBUG("Disk     -> extrapolated track parameters on Disk is null");
+  } else {
+    bDisk = true;
+    double Rms = sqrt((param2->position().x())*(param2->position().x()) + (param2->position().y())*(param2->position().y()));
+    ATH_MSG_DEBUG("Disk     -> eta: " << param2->eta() << ", phi: " << param2->position().phi() << ", Z: " << param2->position().z() << ", Rms: " << Rms);
+  }
+
+
+  surface1 = 0;
+  surface2 = 0;
+  disc = 0;
+  barrel = 0;
+  matrix = 0;
+
+  ATH_MSG_DEBUG("bCylinder:" << bCylinder << ", bDisk:" << bDisk );
+
+  delete matrix;
+  delete disc;
+  delete barrel;
+
+  if ( bCylinder == true && bDisk == true ){
+    extFlag = 0;
+    return param1;
+  } else if ( bCylinder == true && bDisk == false){
+    extFlag = 1;
+    return param1;
+  } else if ( bCylinder == false && bDisk == true){
+    extFlag = 2;
+    return param2;
+  } else {
+    extFlag = 3;
+    return param1;
+  }
+
+  return param1;
+}
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/FtfRoadDefiner.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/FtfRoadDefiner.h
new file mode 100644
index 0000000000000000000000000000000000000000..16021539abad7ba8e59e98fbf8180a99063ff5dd
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/FtfRoadDefiner.h
@@ -0,0 +1,66 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef  TRIGL2MUONSA_FTFROADDEFINER_H
+#define  TRIGL2MUONSA_FTFROADDEFINER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+/* #include "RpcData.h" */
+/* #include "RpcPatFinder.h" */
+#include "MuonRoad.h"
+/* #include "MdtRegion.h" */
+/* #include "RpcFitResult.h" */
+/* #include "BarrelRoadData.h" */
+/* #include "RecMuonRoI.h" */
+
+/* #include "IRegionSelector/IRegSelTool.h" */
+#include "xAODTracking/TrackParticleContainer.h"
+
+#include "TrkExInterfaces/IExtrapolator.h"
+
+using Amg::Transform3D;
+
+namespace TrigL2MuonSA {
+
+  // --------------------------------------------------------------------------------
+  // --------------------------------------------------------------------------------
+
+  class FtfRoadDefiner: public AthAlgTool
+  {
+  public:
+
+    FtfRoadDefiner(const std::string& type,
+		   const std::string& name,
+		   const IInterface*  parent);
+
+    virtual StatusCode initialize() override;
+
+  public:
+    StatusCode defineRoad( const xAOD::TrackParticle* idtrack,
+			   TrigL2MuonSA::MuonRoad&    muonRoad);
+    /* void setMdtGeometry( const ServiceHandle<IRegSelSvc>& regionSelector, */
+    /* 			 const Muon::MuonIdHelperTool* muonIdHelperTool); */
+    /* void unsetRpc(bool insideOut, Gaudi::Property<bool>* use_rpc); */
+    const Trk::TrackParameters* extTrack( const xAOD::TrackParticle* trk, double R, double halflength, int& extFlag );
+
+  protected:
+
+  private:
+    /* const BarrelRoadData*  m_roadData; */
+    ToolHandle<Trk::IExtrapolator> m_extrapolator{
+      this, "IOExtrapolator", "Trk::Extrapolator/AtlasExtrapolator"};
+
+    /* bool m_use_ftf; */
+
+    /* ToolHandle<IRegSelTool> m_regionSelector; */
+    /* const Muon::MuonIdHelperTool* m_muonIdHelperTool; */
+  };
+
+  // --------------------------------------------------------------------------------
+  // --------------------------------------------------------------------------------
+}
+
+#endif // TRIGL2MUONSA_FTFROADDEFINER_H
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MdtRegionDefiner.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MdtRegionDefiner.cxx
index a6946c94e455c3fa3194bdc74678bf5e92cd632e..800777bc096eb84bc21c914a28cb0d5040356b2a 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MdtRegionDefiner.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MdtRegionDefiner.cxx
@@ -40,6 +40,7 @@ StatusCode TrigL2MuonSA::MdtRegionDefiner::getMdtRegions(const LVL1::RecMuonRoI*
 							 TrigL2MuonSA::MuonRoad& muonRoad,
 							 TrigL2MuonSA::MdtRegion& mdtRegion)
 {
+  const double ZERO_LIMIT = 1e-5;
   mdtRegion.Clear();
   
   int sectors[2];
@@ -178,6 +179,11 @@ StatusCode TrigL2MuonSA::MdtRegionDefiner::getMdtRegions(const LVL1::RecMuonRoI*
   else {
     for (int i=0; i<6; i++){
       for (int j=0; j<2; j++){
+        if (abs(muonRoad.extFtfMiddlePhi) > ZERO_LIMIT) { // for inside-out
+          if (i==4) muonRoad.phi[9][j] = muonRoad.extFtfMiddlePhi;
+          else if (i==5) muonRoad.phi[10][j] = muonRoad.extFtfMiddlePhi;
+          else muonRoad.phi[i][j] = muonRoad.extFtfMiddlePhi;
+        }
         if (i==4) muonRoad.phi[9][j] = p_roi->phi();
         else if (i==5) muonRoad.phi[10][j] = p_roi->phi();
         else muonRoad.phi[i][j] = p_roi->phi();
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.cxx
index 8f45444ac4f8522833f252f2ae9415e92c1d0ead..d963f86054986ae0eaec038db4c7239f420799df 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.cxx
@@ -172,6 +172,7 @@ void TrigL2MuonSA::MuFastDataPreparator::setExtrapolatorTool(ToolHandle<ITrigMuo
 
 StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRoI*     p_roi,
                                                            const TrigRoiDescriptor*    p_roids,
+                                                           const bool                  insideOut,
                                                            TrigL2MuonSA::RpcHits&      rpcHits,
                                                            TrigL2MuonSA::MuonRoad&     muonRoad,
                                                            TrigL2MuonSA::MdtRegion&    mdtRegion,
@@ -184,7 +185,7 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
   
   StatusCode sc = StatusCode::SUCCESS;
   
-  if(m_use_rpc) {
+  if(m_use_rpc && !insideOut) {
 
     m_rpcPatFinder->clear();
 
@@ -201,6 +202,8 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
     if (!sc.isSuccess()) {
       ATH_MSG_DEBUG("Error in RPC data prepapration. Continue using RoI");
     }
+  } else {
+    ATH_MSG_DEBUG("Skip RpcDataPreparator");
   }
 
   SG::ReadCondHandle<RpcCablingCondData> readHandle{m_readKey};
@@ -217,6 +220,7 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
   ATH_MSG_DEBUG("nr of RPC hits=" << rpcHits.size());
 
   sc = m_rpcRoadDefiner->defineRoad(p_roi,
+                                    insideOut,
                                     muonRoad,
                                     rpcHits,
                                     &m_rpcPatFinder,
@@ -254,6 +258,7 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
 
 StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRoI*     p_roi,
                                                            const TrigRoiDescriptor*    p_roids,
+                                                           const bool                  insideOut,
                                                            TrigL2MuonSA::TgcHits&      tgcHits,
                                                            TrigL2MuonSA::MuonRoad&     muonRoad,
                                                            TrigL2MuonSA::MdtRegion&    mdtRegion,
@@ -266,15 +271,21 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
 {
   StatusCode sc = StatusCode::SUCCESS;
   ATH_MSG_DEBUG("RoI eta/phi=" << p_roi->eta() << "/" << p_roi->phi());
-  
-  sc = m_tgcDataPreparator->prepareData(p_roi,
-                                        tgcHits);
+
+  if(!insideOut) {
+    sc = m_tgcDataPreparator->prepareData(p_roi,
+                                          tgcHits);
+  } else {
+    ATH_MSG_DEBUG("Skip TgcDataPreparator");
+  }
+
   if (!sc.isSuccess()) {
     ATH_MSG_DEBUG("Error in TGC data preparation. Continue using RoI");
   }
   ATH_MSG_DEBUG("nr of TGC hits=" << tgcHits.size());
-  
+
   sc = m_tgcRoadDefiner->defineRoad(p_roi,
+                                    insideOut,
                                     tgcHits,
                                     muonRoad,
                                     tgcFitResult);
@@ -282,7 +293,7 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
     ATH_MSG_WARNING("Error in road definition.");
     return sc;
   }
-  
+
   sc = m_mdtDataPreparator->prepareData(p_roi,
                                         p_roids,
                                         tgcFitResult,
@@ -297,7 +308,7 @@ StatusCode TrigL2MuonSA::MuFastDataPreparator::prepareData(const LVL1::RecMuonRo
   }
   ATH_MSG_DEBUG("nr of MDT (normal)  hits=" << mdtHits_normal.size());
   ATH_MSG_DEBUG("nr of MDT (overlap) hits=" << mdtHits_overlap.size());
-  
+
   if(!m_cscDataPreparator.empty()) {
     sc = m_cscDataPreparator->prepareData(p_roids,
 					  muonRoad,
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.h
index abe72e71d6dcf806b0aa0a54cb8de6f0ed846ffa..0f896e18374be9f4368ac61c76d35bda3bdfee29 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.h
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastDataPreparator.h
@@ -55,6 +55,7 @@ class MuFastDataPreparator: public AthAlgTool {
   
   StatusCode prepareData(const LVL1::RecMuonRoI*     p_roi,
 			 const TrigRoiDescriptor*    p_roids,
+			 const bool                  insideOut,
 			 TrigL2MuonSA::RpcHits&      rpcHits,
 			 TrigL2MuonSA::MuonRoad&     muonRoad,
 			 TrigL2MuonSA::MdtRegion&    mdtRegion,
@@ -64,6 +65,7 @@ class MuFastDataPreparator: public AthAlgTool {
   
   StatusCode prepareData(const LVL1::RecMuonRoI*     p_roi,
 			 const TrigRoiDescriptor*    p_roids,
+			 const bool                  insideOut,
 			 TrigL2MuonSA::TgcHits&      tgcHits,
 			 TrigL2MuonSA::MuonRoad&     muonRoad,
 			 TrigL2MuonSA::MdtRegion&    mdtRegion,
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.cxx
index 42fde417509e27b993fe9d96005f611d73057e46..130cd73bf37e8bc2c3a08dd1fcb41baf0ed53d0e 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.cxx
@@ -82,9 +82,11 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::setMCFlag(BooleanProperty use_mcLU
 // --------------------------------------------------------------------------------
 
 StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuonRoI*    p_roi,
+                                                              const TrigL2MuonSA::MuonRoad& muonRoad,
                                                               TrigL2MuonSA::RpcFitResult& rpcFitResult,
                                                               std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns)
 {
+  const double ZERO_LIMIT = 1e-5;
 
   //
   for (TrigL2MuonSA::TrackPattern& itTrack : v_trackPatterns) { // loop for track candidates
@@ -93,13 +95,17 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuo
       //      itTrack->phiMSDir = rpcFitResult.phiDir;
       itTrack.phiMSDir = (cos(rpcFitResult.phi)!=0)? tan(rpcFitResult.phi): 0;
     } else {
-      itTrack.phiMSDir = (cos(p_roi->phi())!=0)? tan(p_roi->phi()): 0;
+      if ( abs(muonRoad.extFtfMiddlePhi) > ZERO_LIMIT ) { //inside-out
+	itTrack.phiMSDir = (cos(muonRoad.extFtfMiddlePhi)!=0)? tan(muonRoad.extFtfMiddlePhi): 0;
+      } else {
+	itTrack.phiMSDir = (cos(p_roi->phi())!=0)? tan(p_roi->phi()): 0;
+      }
       itTrack.isRpcFailure = true;
     }
 
     ATH_CHECK( superPointFitter(itTrack) );
   }
-  // 
+  //
 
   return StatusCode::SUCCESS;
 }
@@ -107,17 +113,23 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuo
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 
-StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuonRoI*   p_roi,
-                                                              TrigL2MuonSA::TgcFitResult& tgcFitResult,
-                                                              std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns)
+StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPointsSimple(const LVL1::RecMuonRoI*   p_roi,
+								    const TrigL2MuonSA::MuonRoad& muonRoad,
+								    TrigL2MuonSA::TgcFitResult& tgcFitResult,
+								    std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns)
 {
+  const double ZERO_LIMIT = 1e-5;
   
   for (TrigL2MuonSA::TrackPattern& itTrack : v_trackPatterns) { // loop for track candidates
 
     if (tgcFitResult.isSuccess) {
       itTrack.phiMSDir = tgcFitResult.phiDir;
     } else {
-      itTrack.phiMSDir = (cos(p_roi->phi())!=0)? tan(p_roi->phi()): 0;
+      if ( abs(muonRoad.extFtfMiddlePhi) > ZERO_LIMIT ) { //insideout
+	itTrack.phiMSDir = (cos(muonRoad.extFtfMiddlePhi)!=0)? tan(muonRoad.extFtfMiddlePhi): 0;
+      } else {
+	itTrack.phiMSDir = (cos(p_roi->phi())!=0)? tan(p_roi->phi()): 0;
+      }
       itTrack.isTgcFailure = true;
     }
 
@@ -125,7 +137,7 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuo
 
     ATH_CHECK( m_nswStationFitter->superPointFitter(p_roi, itTrack) );
   }
-  // 
+  //
   return StatusCode::SUCCESS;
 }
 
@@ -137,7 +149,7 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuo
                                                               TrigL2MuonSA::TgcFitResult& tgcFitResult,
                                                               std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns)
 {
-  
+
   for (TrigL2MuonSA::TrackPattern& itTrack : v_trackPatterns) { // loop for track candidates
 
     if (tgcFitResult.isSuccess) {
@@ -152,6 +164,10 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuo
     makeReferenceLine(itTrack, muonRoad);
     ATH_CHECK( m_alphaBetaEstimate->setAlphaBeta(p_roi, tgcFitResult, itTrack, muonRoad) );
 
+    if ( itTrack.etaBin < -1 ) {
+      itTrack.etaBin = static_cast<int>((fabs(muonRoad.extFtfMiddleEta)-1.)/0.05);
+    }
+
     ATH_CHECK( m_ptFromAlphaBeta->setPt(itTrack,tgcFitResult) );
 
     double exInnerA = fromAlphaPtToInn(tgcFitResult,itTrack);
@@ -162,7 +178,7 @@ StatusCode TrigL2MuonSA::MuFastStationFitter::findSuperPoints(const LVL1::RecMuo
     ATH_CHECK( m_nswStationFitter->superPointFitter(p_roi, itTrack) );
 
   }
-  // 
+  //
   return StatusCode::SUCCESS;
 }
 
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.h
index 0f407bb29318abdba42f6b8679d7569a242ff579..6cc69744fb6abfc0e50ec0d0e272af6a1310aa37 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.h
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastStationFitter.h
@@ -38,11 +38,13 @@ class MuFastStationFitter: public AthAlgTool
     
    public:
       StatusCode findSuperPoints(const LVL1::RecMuonRoI*    p_roi,
+				 const TrigL2MuonSA::MuonRoad& muonRoad,
 				 TrigL2MuonSA::RpcFitResult& rpcFitResult,
 				 std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns);
-      StatusCode findSuperPoints(const LVL1::RecMuonRoI*    p_roi,
-				 TrigL2MuonSA::TgcFitResult& tgcFitResult,
-				 std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns);
+      StatusCode findSuperPointsSimple(const LVL1::RecMuonRoI*    p_roi,
+				       const TrigL2MuonSA::MuonRoad& muonRoad,
+				       TrigL2MuonSA::TgcFitResult& tgcFitResult,
+				       std::vector<TrigL2MuonSA::TrackPattern>& v_trackPatterns);
 
       StatusCode findSuperPoints(const LVL1::RecMuonRoI*    p_roi,
                                  const TrigL2MuonSA::MuonRoad& muonRoad,
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.cxx
index 7d6359611974ee8abd68087fc87e2064d7e9f41a..b646c6da7c792f6c5ecead88590306aec82c0d25 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.cxx
@@ -111,6 +111,12 @@ HLT::ErrorCode MuFastSteering::hltInitialize()
     return HLT::BAD_JOB_SETUP;
   }
 
+  // FtfRoadDefiner
+  if ( m_ftfRoadDefiner.retrieve().isFailure() ) {
+    ATH_MSG_ERROR("Could not retrieve " << m_ftfRoadDefiner);
+    return HLT::BAD_JOB_SETUP;
+  }
+
   // Set service tools
   m_trackExtrapolator->setExtrapolatorTool(&m_backExtrapolatorTool);
   m_dataPreparator->setExtrapolatorTool(&m_backExtrapolatorTool);
@@ -190,6 +196,16 @@ HLT::ErrorCode MuFastSteering::hltInitialize()
     ATH_MSG_ERROR("ReadHandleKey for DataVector<LVL1::RecMuonRoI> key:" << m_recRoiCollectionKey.key() << " initialize Failure!");
     return HLT::BAD_JOB_SETUP;
   }
+  // for Inside-Out mode ---
+  if (m_FTFtrackKey.initialize(m_insideOut).isFailure() ) {
+    ATH_MSG_ERROR("ReadHandleKey for xAOD::TrackParticleContainer key:" << m_FTFtrackKey.key() << " initialize Failure!");
+    return HLT::BAD_JOB_SETUP;
+  }
+  if (m_outputCBmuonCollKey.initialize(m_insideOut).isFailure() ) {
+    ATH_MSG_ERROR("ReadHandleKey for xAOD::L2CombinedMuonContainer key:" << m_outputCBmuonCollKey.key() << " initialize Failure!");
+    return HLT::BAD_JOB_SETUP;
+  }
+  // ----
   if (m_muFastContainerKey.initialize().isFailure() ) {
     ATH_MSG_ERROR("WriteHandleKey for xAOD::L2StandAloneMuonContainer key:" << m_muFastContainerKey.key() << " initialize Failure!");
     return HLT::BAD_JOB_SETUP;
@@ -263,6 +279,7 @@ const LVL1::RecMuonRoI* matchingRecRoI( uint32_t roiWord,
 StatusCode MuFastSteering::execute()
 {
   ATH_MSG_DEBUG("StatusCode MuFastSteering::execute start");
+  ATH_MSG_DEBUG("InsideOutMode: " << m_insideOut);
 
   auto totalTimer = Monitored::Timer( "TIME_Total" );
   auto monitorIt	= Monitored::Group(m_monTool, totalTimer );
@@ -351,10 +368,39 @@ StatusCode MuFastSteering::execute()
   auto muMsContainer = SG::makeHandle(m_muMsContainerKey, ctx);
   ATH_CHECK(muMsContainer.record(std::make_unique<TrigRoiDescriptorCollection>()));
 
-  // to StatusCode findMuonSignature()
-  ATH_CHECK(findMuonSignature(internalRoI, recRoIVector,
-			      *muFastContainer, *muIdContainer, *muMsContainer, *muCompositeContainer ));
 
+  // Inside-out L2Muon mode
+  if(m_insideOut) {
+    ATH_MSG_DEBUG("start inside-out mode...");
+
+    auto muonCBColl = SG::makeHandle (m_outputCBmuonCollKey, ctx);
+    ATH_CHECK( muonCBColl.record (std::make_unique<xAOD::L2CombinedMuonContainer>(),
+				  std::make_unique<xAOD::L2CombinedMuonAuxContainer>()) );
+
+    auto trackHandle = SG::makeHandle( m_FTFtrackKey, ctx );
+    const xAOD::TrackParticleContainer *tracks = trackHandle.cptr();
+    if (!trackHandle.isValid()){
+      ATH_MSG_ERROR("ReadHandle for TrackParticleContainer key:" << m_FTFtrackKey.key() << " isn't Valid");
+      return StatusCode::FAILURE;
+    }
+
+    ATH_CHECK(findMuonSignatureIO(*tracks, internalRoI, recRoIVector,
+				  *muonCBColl, *muFastContainer, *muIdContainer, *muMsContainer ));
+
+    ATH_MSG_DEBUG("REGTEST: xAOD::L2CombinedMuonContainer key:" << m_outputCBmuonCollKey.key() << " size = " << muonCBColl->size());
+    xAOD::L2CombinedMuonContainer::const_iterator p_CBmuon = (*muonCBColl).begin();
+    xAOD::L2CombinedMuonContainer::const_iterator p_CBmuonEn = (*muonCBColl).end();
+    for (;p_CBmuon != p_CBmuonEn; ++p_CBmuon) {
+      ATH_MSG_DEBUG("REGTEST: xAOD::L2CombinedMuonContainer key:" << m_outputCBmuonCollKey.key() << " pt = " << (*p_CBmuon)->pt() << " GeV");
+      ATH_MSG_DEBUG("REGTEST: xAOD::L2CombinedMuonContainer key:" << m_outputCBmuonCollKey.key() << " eta/phi = " << (*p_CBmuon)->eta() << "/" << (*p_CBmuon)->phi());
+    }
+
+  }
+  else {
+    // to StatusCode findMuonSignature()
+    ATH_CHECK(findMuonSignature(internalRoI, recRoIVector,
+				*muFastContainer, *muIdContainer, *muMsContainer, *muCompositeContainer ));
+  }
 
   // DEBUG TEST: Recorded data objects
   ATH_MSG_DEBUG("Recorded data objects");
@@ -627,6 +673,7 @@ StatusCode MuFastSteering::findMuonSignature(const std::vector<const TrigRoiDesc
       m_tgcHits.clear();
       sc = m_dataPreparator->prepareData(*p_roi,
                                          *p_roids,
+                                         m_insideOut,
                                          m_rpcHits,
                                          m_muonRoad,
                                          m_mdtRegion,
@@ -681,6 +728,7 @@ StatusCode MuFastSteering::findMuonSignature(const std::vector<const TrigRoiDesc
       if (m_use_timer) m_timingTimers[ITIMER_STATION_FITTER]->resume();
       stationFitterTimer.start();
       sc = m_stationFitter->findSuperPoints(*p_roi,
+                                            m_muonRoad,
                                             m_rpcFitResult,
                                             trackPatterns);
       if (!sc.isSuccess()) {
@@ -723,6 +771,7 @@ StatusCode MuFastSteering::findMuonSignature(const std::vector<const TrigRoiDesc
       m_tgcHits.clear();
       sc = m_dataPreparator->prepareData(*p_roi,
                                          *p_roids,
+                                         m_insideOut,
                                          m_tgcHits,
                                          m_muonRoad,
                                          m_mdtRegion,
@@ -773,9 +822,10 @@ StatusCode MuFastSteering::findMuonSignature(const std::vector<const TrigRoiDesc
       if (m_use_timer) m_timingTimers[ITIMER_STATION_FITTER]->resume();
       stationFitterTimer.start();
       if(!m_use_new_segmentfit){
-        sc = m_stationFitter->findSuperPoints(*p_roi,
-                                              m_tgcFitResult,
-                                              trackPatterns);
+        sc = m_stationFitter->findSuperPointsSimple(*p_roi,
+						    m_muonRoad,
+						    m_tgcFitResult,
+						    trackPatterns);
       }else{
         sc = m_stationFitter->findSuperPoints(*p_roi,
                                               m_muonRoad,
@@ -939,6 +989,384 @@ StatusCode MuFastSteering::findMuonSignature(const std::vector<const TrigRoiDesc
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 
+StatusCode MuFastSteering::findMuonSignatureIO(const xAOD::TrackParticleContainer          idtracks,
+					       const std::vector<const TrigRoiDescriptor*> roids,
+					       const std::vector<const LVL1::RecMuonRoI*>  muonRoIs,
+					       DataVector<xAOD::L2CombinedMuon>&           outputCBs,
+					       DataVector<xAOD::L2StandAloneMuon>&         outputSAs,
+					       TrigRoiDescriptorCollection&                outputID,
+					       TrigRoiDescriptorCollection&                outputMS
+					       )
+{
+  ATH_MSG_DEBUG("StatusCode MuFastSteering::findMuonSignatureIO start");
+  StatusCode sc = StatusCode::SUCCESS;
+
+  auto prepTimer           = Monitored::Timer( "TIME_Data_Preparator" );
+  auto patternTimer        = Monitored::Timer( "TIME_Pattern_Finder" );
+  auto stationFitterTimer  = Monitored::Timer( "TIME_Station_Fitter" );
+  auto trackFitterTimer    = Monitored::Timer( "TIME_Track_Fitter" );
+  auto trackExtraTimer     = Monitored::Timer( "TIME_Track_Extrapolator" );
+  auto calibrationTimer    = Monitored::Timer( "TIME_Calibration_Streamer" );
+
+  auto monitorIt       = Monitored::Group(m_monTool, prepTimer, patternTimer, stationFitterTimer,
+					  trackFitterTimer, trackExtraTimer, calibrationTimer );
+
+  if (m_use_timer) {
+    for (unsigned int i_timer=0; i_timer<m_timingTimers.size(); i_timer++) {
+      m_timingTimers[i_timer]->start();
+      m_timingTimers[i_timer]->pause();
+    }
+  }
+
+  if (m_use_timer) m_timingTimers[ITIMER_TOTAL_PROCESSING]->resume();
+  if (m_use_timer) m_timingTimers[ITIMER_DATA_PREPARATOR]->resume();
+
+  DataVector<const TrigRoiDescriptor>::const_iterator p_roids;
+  DataVector<const LVL1::RecMuonRoI>::const_iterator p_roi;
+
+  //int npass = 0;
+  // muonRoIs = RecMURoIs, roids = MURoIs
+  p_roids = roids.begin();
+  for (p_roi=(muonRoIs).begin(); p_roi!=(muonRoIs).end(); ++p_roi) {
+    //p_roi = (muonRoIs.begin());
+    ATH_MSG_DEBUG("roi eta/phi: " << (*p_roi)->eta() << "/" << (*p_roi)->phi());
+
+    // idtracks loop
+    if ( (idtracks).size()== 0) ATH_MSG_DEBUG("IO TEST: xAOD::TrackParticleContainer has 0 tracks --> Can not use FTF tracks...");
+    else  ATH_MSG_DEBUG("IO TEST: xAOD::TrackParticleContainer has " << (idtracks).size() << " tracks --> Start inside-out mode!");
+
+    std::vector<TrigL2MuonSA::TrackPattern> trackPatterns;
+    for (auto idtrack : idtracks) {
+      ATH_MSG_DEBUG("IO TEST: FTF track key:" << m_FTFtrackKey.key() << " pt = " << idtrack->pt()/1000 << " GeV");
+      ATH_MSG_DEBUG("IO TEST: FTF track key:" << m_FTFtrackKey.key() << " eta/phi = " << idtrack->eta() << "/" << idtrack->phi());
+
+      prepTimer.start();
+      m_mdtHits_normal.clear();
+      m_mdtHits_overlap.clear();
+      m_cscHits.clear();
+      m_stgcHits.clear();
+      m_mmHits.clear();
+      m_rpcFitResult.Clear();
+      m_tgcFitResult.Clear();
+
+      m_muonRoad.Clear();
+
+      sc = m_ftfRoadDefiner->defineRoad(idtrack, m_muonRoad);
+      if (!sc.isSuccess()) {
+	ATH_MSG_WARNING("FtfRoadDefiner failed");
+	TrigL2MuonSA::TrackPattern trackPattern;
+	trackPatterns.push_back(trackPattern);
+	return StatusCode::SUCCESS;
+      } else {
+	ATH_MSG_DEBUG("FtfRoadDefiner::defineRoad success");
+      }
+
+      if ( std::abs(idtrack->eta()) < 1.05 ){
+	ATH_MSG_DEBUG("FTF track at IP is in  Barrel: " << idtrack->eta());
+      } else {
+	ATH_MSG_DEBUG("FTF track at IP is in  Endcap: " << idtrack->eta());
+      }
+
+      if ( std::abs(m_muonRoad.extFtfMiddleEta) < 1.05 ){ // Barrel Inside-out
+	ATH_MSG_DEBUG("m_muonRoad.extFtfMiddleEta Barrel: " << m_muonRoad.extFtfMiddleEta);
+
+	ATH_MSG_DEBUG("Barrel algorithm of IOmode starts");
+
+	m_muonRoad.setScales(m_scaleRoadBarrelInner,
+			     m_scaleRoadBarrelMiddle,
+			     m_scaleRoadBarrelOuter);
+
+	// Data preparation
+	m_rpcHits.clear();
+	m_tgcHits.clear();
+	sc = m_dataPreparator->prepareData(*p_roi,
+					   *p_roids,
+					   m_insideOut,
+					   m_rpcHits,
+					   m_muonRoad,
+					   m_mdtRegion,
+					   m_rpcFitResult,
+					   m_mdtHits_normal,
+					   m_mdtHits_overlap);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Data preparation failed");
+	  TrigL2MuonSA::TrackPattern trackPattern;
+	  trackPatterns.push_back(trackPattern);
+	  // Update output trigger element
+	  updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+	} else {
+	  ATH_MSG_DEBUG("Data preparation success");
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_DATA_PREPARATOR]->pause();
+	prepTimer.stop();
+
+	// if ( m_rpcErrToDebugStream && m_dataPreparator->isRpcFakeRoi() ) {
+	//   ATH_MSG_ERROR("Invalid RoI in RPC data found: event to debug stream");
+	//   TrigL2MuonSA::TrackPattern trackPattern;
+	//   trackPatterns.push_back(trackPattern);
+	//   // Update output trigger element
+	//   updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+	// 		      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      // m_stgcHits, m_mmHits,
+	// 		      trackPatterns, outputSAs, outputID, outputMS);
+	//   return StatusCode::FAILURE;
+	// }
+
+	// Pattern finding
+	if (m_use_timer) m_timingTimers[ITIMER_PATTERN_FINDER]->resume();
+	patternTimer.start();
+	sc = m_patternFinder->findPatterns(m_muonRoad,
+					   m_mdtHits_normal,
+					   trackPatterns);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Pattern finder failed");
+	  // Update output trigger element
+	  updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_PATTERN_FINDER]->pause();
+	patternTimer.stop();
+
+	// Superpoint fit
+	if (m_use_timer) m_timingTimers[ITIMER_STATION_FITTER]->resume();
+	stationFitterTimer.start();
+	sc = m_stationFitter->findSuperPoints(*p_roi,
+					      m_muonRoad,
+					      m_rpcFitResult,
+					      trackPatterns);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Super point fitter failed");
+	  // Update output trigger element
+	  updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_STATION_FITTER]->pause();
+	stationFitterTimer.stop();
+
+	// Track fitting
+	if (m_use_timer) m_timingTimers[ITIMER_TRACK_FITTER]->resume();
+	trackFitterTimer.start();
+	sc = m_trackFitter->findTracks(*p_roi,
+				       m_rpcFitResult,
+				       trackPatterns);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Track fitter failed");
+	  // Update output trigger element
+	  updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+        }
+	if (m_use_timer) m_timingTimers[ITIMER_TRACK_FITTER]->pause();
+        trackFitterTimer.stop();
+
+      } else { // Endcap Inside-out
+	ATH_MSG_DEBUG("m_muonRoad.extFtfMiddleEta Endcap: " << m_muonRoad.extFtfMiddleEta);
+	ATH_MSG_DEBUG("Endcap algorithm of IOmode starts");
+
+	prepTimer.start();
+	// Data preparation
+	m_rpcHits.clear();
+	m_tgcHits.clear();
+	sc = m_dataPreparator->prepareData(*p_roi,
+					   *p_roids,
+					   m_insideOut,
+					   m_tgcHits,
+					   m_muonRoad,
+					   m_mdtRegion,
+					   m_tgcFitResult,
+					   m_mdtHits_normal,
+					   m_mdtHits_overlap,
+					   m_cscHits,
+					   m_stgcHits,
+					   m_mmHits);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Data preparation failed");
+	  TrigL2MuonSA::TrackPattern trackPattern;
+	  trackPatterns.push_back(trackPattern);
+	  // Update output trigger element
+	  updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+	} else{
+	  ATH_MSG_DEBUG("Data preparation success");
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_DATA_PREPARATOR]->pause();
+	prepTimer.stop();
+
+	// Pattern finding
+	if (m_use_timer) m_timingTimers[ITIMER_PATTERN_FINDER]->resume();
+	patternTimer.start();
+	sc = m_patternFinder->findPatterns(m_muonRoad,
+					   m_mdtHits_normal,
+					   m_stgcHits,
+					   m_mmHits,
+					   trackPatterns);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Pattern finder failed");
+	  // Update output trigger element
+          updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_PATTERN_FINDER]->pause();
+	patternTimer.stop();
+
+	// Superpoint fit
+	if (m_use_timer) m_timingTimers[ITIMER_STATION_FITTER]->resume();
+	stationFitterTimer.start();
+	sc = m_stationFitter->findSuperPointsSimple(*p_roi,
+						    m_muonRoad,
+						    m_tgcFitResult,
+						    trackPatterns);
+	/////csc SuperPoint
+	m_cscsegmaker->FindSuperPointCsc(m_cscHits,trackPatterns,m_tgcFitResult,m_muonRoad);
+	if (!sc.isSuccess()) {
+	  ATH_MSG_WARNING("Super point fitter failed");
+	  // Update output trigger element
+          updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+	  return StatusCode::SUCCESS;
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_STATION_FITTER]->pause();
+	stationFitterTimer.stop();
+
+	// Track fittingh
+        if (m_use_timer) m_timingTimers[ITIMER_TRACK_FITTER]->resume();
+	trackFitterTimer.start();
+        sc = m_trackFitter->findTracks(*p_roi,
+				       m_tgcFitResult,
+				       trackPatterns,
+				       m_muonRoad);
+        if (!sc.isSuccess()) {
+          ATH_MSG_WARNING("Track fitter failed");
+          // Update output trigger element
+	  updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			      m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			      m_stgcHits, m_mmHits,
+			      trackPatterns, outputSAs, outputID, outputMS);
+          return StatusCode::SUCCESS;
+	}
+	if (m_use_timer) m_timingTimers[ITIMER_TRACK_FITTER]->pause();
+	trackFitterTimer.stop();
+
+      }
+
+      // fix if eta is strange
+      for (unsigned int i=0 ;i<trackPatterns.size(); i++) {
+	TrigL2MuonSA::TrackPattern track = trackPatterns[i];
+	const float ETA_LIMIT       = 2.8;
+	const float DELTA_ETA_LIMIT = 1.0;
+	float roiEta = (*p_roi)->eta();
+	const float ZERO_LIMIT = 1.e-5;
+	if (fabs(track.pt) > ZERO_LIMIT
+	    && ( fabs(track.etaMap) > ETA_LIMIT || fabs(track.etaMap-roiEta) > DELTA_ETA_LIMIT ) ) {
+          trackPatterns[i].etaMap = roiEta;
+        }
+      }
+
+      // // Track extrapolation for ID combined
+      // if (m_use_timer) m_timingTimers[ITIMER_TRACK_EXTRAPOLATOR]->resume();
+      // trackExtraTimer.start();
+      // sc = m_trackExtrapolator->extrapolateTrack(trackPatterns, m_winPt);
+      // if (sc != StatusCode::SUCCESS) {
+      // 	ATH_MSG_WARNING("Track extrapolator failed");
+      // 	// Update output trigger element
+      // 	updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+      // 			    m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+      // 			    m_stgcHits, m_mmHits,
+      // 			    trackPatterns, outputSAs, outputID, outputMS);
+      // 	return StatusCode::SUCCESS;
+      // }
+      // if (m_use_timer) m_timingTimers[ITIMER_TRACK_EXTRAPOLATOR]->pause();
+      // trackExtraTimer.stop();
+
+      // Update monitoring variables
+      sc = updateMonitor(*p_roi, m_mdtHits_normal, trackPatterns );
+      if (sc != StatusCode::SUCCESS) {
+	ATH_MSG_WARNING("Failed to update monitoring variables");
+	// Update output trigger element
+        updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			    m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			    m_stgcHits, m_mmHits,
+			    trackPatterns, outputSAs, outputID, outputMS);
+	return StatusCode::SUCCESS;
+      }
+
+      // Update output trigger element
+      updateOutputObjects(*p_roi, *p_roids, m_muonRoad, m_mdtRegion, m_rpcHits, m_tgcHits,
+			  m_rpcFitResult, m_tgcFitResult, m_mdtHits_normal, m_cscHits,
+			  m_stgcHits, m_mmHits,
+			  trackPatterns, outputSAs, outputID, outputMS);
+
+
+    }
+
+    ATH_MSG_DEBUG("trackPatterns->size(): " << trackPatterns.size());
+    for (unsigned int i = 0; i< trackPatterns.size(); i++){
+      TrigL2MuonSA::TrackPattern trackPattern = trackPatterns[i];
+      ATH_MSG_DEBUG("trackPattern pt/eta/phi: " << trackPattern.pt << "/" << trackPattern.etaVtx << "/" << trackPattern.phiVtx);
+    }
+
+    ATH_MSG_DEBUG("outputSAs size: " << outputSAs.size());
+    ATH_MSG_DEBUG("idtracks size: " << idtracks.size());
+    for (unsigned int i = 0; i< outputSAs.size(); i++){
+      xAOD::L2StandAloneMuon* outputSA = outputSAs[i];
+      ATH_MSG_DEBUG("outputSA pt/eta/phi: " << outputSA->pt() << "/" << outputSA->eta() << "/" << outputSA->phi());
+      ATH_MSG_DEBUG("idtrack pt/eta/phi: " << (idtracks[i]->pt())/1000. << "/" << idtracks[i]->eta() << "/" << idtracks[i]->phi());
+      xAOD::L2CombinedMuon* muonCB = new xAOD::L2CombinedMuon();
+      muonCB->makePrivateStore();
+      muonCB->setStrategy(-9);
+      muonCB->setErrorFlag(-9);
+      muonCB->setPt((idtracks[i]->pt())/1000.);
+      muonCB->setEta(idtracks[i]->eta());
+      muonCB->setPhi(idtracks[i]->phi());
+      ElementLink<xAOD::L2StandAloneMuonContainer> muonSAEL(outputSAs, i);
+      muonCB->setMuSATrackLink(muonSAEL);
+
+      outputCBs.push_back(muonCB);
+    }
+
+    ATH_MSG_DEBUG("outputCBs size: " << outputCBs.size());
+    for (unsigned int i = 0; i< outputCBs.size(); i++){
+      xAOD::L2CombinedMuon* outputCB = outputCBs[i];
+      ATH_MSG_DEBUG("outputCB pt/eta/phi: " << outputCB->pt() << "/" << outputCB->eta() << "/" << outputCB->phi());
+    }
+
+  }
+
+  if (m_use_timer) m_timingTimers[ITIMER_TOTAL_PROCESSING]->pause();
+
+  if (m_use_timer) {
+    for (unsigned int i_timer=0; i_timer<m_timingTimers.size(); i_timer++) {
+      m_timingTimers[i_timer]->stop();
+    }
+  }
+
+  ATH_MSG_DEBUG("StatusCode MuFastSteering::findMuonSignatureIO success");
+  return StatusCode::SUCCESS;
+}
+
+// --------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------
+
 bool MuFastSteering::updateOutputObjects(const LVL1::RecMuonRoI*                        roi,
                                          const TrigRoiDescriptor*                       roids,
                                          const TrigL2MuonSA::MuonRoad&                  muonRoad,
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.h
index ba95ecd9ef5b522399b7d5ad21a2b20ce48a84b2..e61add892ec8fd8de12b0183e49fa950bbd94705 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.h
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastSteering.h
@@ -24,6 +24,7 @@
 #include "GaudiKernel/IIncidentListener.h"
 #include "CscSegmentMaker.h"
 #include "CscRegUtils.h"
+#include "FtfRoadDefiner.h"
 
 //adding a part of DataHandle for AthenaMT
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
@@ -34,6 +35,7 @@
 #include "xAODTrigMuon/L2StandAloneMuonContainer.h"
 #include "xAODTrigger/TrigCompositeAuxContainer.h"
 #include "xAODTrigger/TrigCompositeContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
 #include "AthenaMonitoringKernel/GenericMonitoringTool.h"
 
 class IRegSelSvc;
@@ -84,6 +86,15 @@ class MuFastSteering : public HLT::FexAlgo,
 			       TrigRoiDescriptorCollection&	 		outputMS,
 			       DataVector<xAOD::TrigComposite>&			outputComposite );
 
+  /** findMuonSignatureIO(), includes reconstract algorithms for inside-out mode **/
+  StatusCode findMuonSignatureIO(const xAOD::TrackParticleContainer             idtracks,
+				 const std::vector<const TrigRoiDescriptor*>    roids,
+				 const std::vector<const LVL1::RecMuonRoI*>     muonRoIs,
+				 DataVector<xAOD::L2CombinedMuon>&              outputCBs,
+				 DataVector<xAOD::L2StandAloneMuon>&            outputSAs,
+				 TrigRoiDescriptorCollection&                   outputID,
+				 TrigRoiDescriptorCollection&                   outputMS );
+
   int L2MuonAlgoMap(const std::string& name);
 
   // handler for "UpdateAfterFork" actions
@@ -168,6 +179,8 @@ class MuFastSteering : public HLT::FexAlgo,
 	this, "TrackFitter", "TrigL2MuonSA::MuFastTrackFitter", "track fitter" };
   ToolHandle<TrigL2MuonSA::MuFastTrackExtrapolator>  m_trackExtrapolator {
 	this, "TrackExtrapolator", "TrigL2MuonSA::MuFastTrackExtrapolator", "track extrapolator" };
+  ToolHandle<TrigL2MuonSA::FtfRoadDefiner>           m_ftfRoadDefiner {
+        this, "FtfRoadDefiner", "TrigL2MuonSA::FtfRoadDefiner", "ftf road definer" };
 
   /** Handle to MuonBackExtrapolator tool */
   ToolHandle<ITrigMuonBackExtrapolator> m_backExtrapolatorTool {
@@ -231,6 +244,7 @@ class MuFastSteering : public HLT::FexAlgo,
 
   Gaudi::Property< double > m_winPt { this, "WinPt", 4.0 };
 
+  Gaudi::Property< bool > m_insideOut { this, "InsideOutMode", false, "" };
   Gaudi::Property< bool > m_topoRoad { this, "topoRoad", false, "create road in barrel not to highly overlap surrounding L1 RoIs" };
   Gaudi::Property< float > m_dPhisurrRoI { this, "dPhisurrRoI", 99, "phi range to find surrounding L1 RoIs" };
   Gaudi::Property< float > m_dEtasurrRoI { this, "dEtasurrRoI", 99, "eta range to find surrounding L1 RoIs" };
@@ -257,6 +271,10 @@ class MuFastSteering : public HLT::FexAlgo,
   SG::ReadHandleKey<DataVector<LVL1::RecMuonRoI>> m_recRoiCollectionKey{
 	this, "RecMuonRoI", "HLT_RecMURoIs", "Name of the input data on LVL1::RecMuonRoI produced by L1Decoder"};
 
+  //ReadHandle FTF Tracks
+  SG::ReadHandleKey<xAOD::TrackParticleContainer> m_FTFtrackKey{
+	this, "TrackParticlesContainerName", "HLT_xAODTracks_Muon", "Name of the input data on xAOD::TrackParticleContainer produced by FTF for Inside-Out mode"};
+
   //WriteHandle <xAOD::L2StandAloneMuonContainer>
   SG::WriteHandleKey<xAOD::L2StandAloneMuonContainer> m_muFastContainerKey{
 	this, "MuonL2SAInfo", "MuonL2SAInfo", "Name of the output data on xAOD::L2StandAloneMuonContainer"};
@@ -273,6 +291,10 @@ class MuFastSteering : public HLT::FexAlgo,
   SG::WriteHandleKey<TrigRoiDescriptorCollection> m_muMsContainerKey{
 	this, "forMS", "forMS", "Name of the output data for MS"};
 
+  //WriteHandle <xAOD::L2CombinedMuonContainer> for Inside-out Mode
+  SG::WriteHandleKey<xAOD::L2CombinedMuonContainer> m_outputCBmuonCollKey{
+	this, "L2IOCB", "MuonL2CBInfo", "output CB Muon container name"};
+
   // Monitor system
   ToolHandle< GenericMonitoringTool > m_monTool { this, "MonTool", "", "Monitoring tool" };
 };
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastTrackFitter.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastTrackFitter.cxx
index ae2002805f87f7ce0a6561a4e22830c8f06be6aa..3d93d7a2e63a7bcb9bd6223c3e46356cdebdb703 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastTrackFitter.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuFastTrackFitter.cxx
@@ -159,6 +159,10 @@ StatusCode TrigL2MuonSA::MuFastTrackFitter::findTracks(const LVL1::RecMuonRoI*
 
      ATH_CHECK( m_alphaBetaEstimate->setAlphaBeta(p_roi, tgcFitResult, itTrack, muonRoad) );
 
+     if ( itTrack.etaBin < -1 ) {
+       itTrack.etaBin = static_cast<int>((fabs(muonRoad.extFtfMiddleEta)-1.)/0.05);
+     }
+
      ATH_CHECK( m_ptFromAlphaBeta->setPt(itTrack,tgcFitResult) );
      
    }
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuonRoad.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuonRoad.h
index fe267bb21abb08bbb214c8c0b308807bde56e00c..f10a7aa577db3b3bbe08751952e9359ac1232847 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuonRoad.h
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/MuonRoad.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef  TRIGL2MUONSA_MUONROAD_H
@@ -33,6 +33,8 @@ namespace TrigL2MuonSA {
       phiRoI     = 0;
       MDT_sector_trigger = 0;
       MDT_sector_overlap = 0;
+      extFtfMiddleEta = 0;
+      extFtfMiddlePhi = 0;
       for(int i=0; i<N_STATION; i++) {
 	scales[i] = 1;
 	for(int j=0; j<N_LAYER; j++) {	  
@@ -41,6 +43,12 @@ namespace TrigL2MuonSA {
 	for(int j=0; j<N_SECTOR; j++) {	  
 	  aw[i][j]   = 0;
 	  bw[i][j]   = 0;
+	  aw_ftf[i][j]  = 0;
+	  bw_ftf[i][j]  = 0;
+	  phi_ftf[i][j] = 0;
+	  eta_ftf[i][j] = 0;
+	  r_ftf[i][j]   = 0;
+	  z_ftf[i][j]   = 0;
 	  phi[i][j]  = 0;
 	}
       }
@@ -78,6 +86,17 @@ namespace TrigL2MuonSA {
     int    MDT_sector_trigger;
     int    MDT_sector_overlap;
 
+    // FTF varibles
+    double extFtfMiddleEta;
+    double extFtfMiddlePhi;
+    double aw_ftf[N_STATION][N_SECTOR];
+    double bw_ftf[N_STATION][N_SECTOR];
+    double phi_ftf[N_STATION][N_SECTOR];
+    double eta_ftf[N_STATION][N_SECTOR];
+    double r_ftf[N_STATION][N_SECTOR];
+    double z_ftf[N_STATION][N_SECTOR];
+    int ext_ftf_flag[N_STATION][N_SECTOR];
+
     std::vector<Identifier> stationList;
 
   };
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.cxx
index 3228d2083fa20ddff2c05f65f8071ffd893e5abe..16cc5e662b05b8b763a8eb7b5492e62af1c7ac12 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.cxx
@@ -19,8 +19,8 @@ TrigL2MuonSA::RpcRoadDefiner::RpcRoadDefiner(const std::string& type,
 {
 }
 
-// -------------------------------------------------------------------------------- 
-// --------------------------------------------------------------------------------                  
+// --------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------
 
 StatusCode TrigL2MuonSA::RpcRoadDefiner::initialize()
 {
@@ -32,6 +32,7 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::initialize()
 // --------------------------------------------------------------------------------
 
 StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*      p_roi,
+						    const bool                   insideOut,
 						    TrigL2MuonSA::MuonRoad&      muonRoad,
 						    TrigL2MuonSA::RpcHits&       /*rpcHits*/,
 						    ToolHandle<RpcPatFinder>*    rpcPatFinder,
@@ -43,11 +44,11 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
 {
 
   const double ZERO_LIMIT = 1e-5;
-  
+
   const int N_LAYER = 5; // 0: inner, 1: middle, 2: outer 4: BME 5: BMG
   const int N_SECTOR = 2; // 0: normal, 1:overlap
 
-  if (m_use_rpc) {
+  if (m_use_rpc && !insideOut) {
     double aw[3]={0.,0.,0.};
     double bw[3]={0.,0.,0.};
     unsigned int rpc_pattern;
@@ -66,7 +67,7 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
     } else {
       rpcFitResult.isSuccess = false;
     }
-    
+
     double phi_middle;
     double phi_outer;
     unsigned int phi_pattern;
@@ -77,35 +78,54 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
     } else {
       rpcFitResult.phi = p_roi->phi();
     }
-  } 
+  } else {
+    ATH_MSG_DEBUG("Skip rpcPatFinder");
+  }
 
   // RPC data is not available -> use RoI 
-  
+
   muonRoad.isEndcap   = false;
-  muonRoad.phiMiddle  = rpcFitResult.phi;
+  if(!insideOut) {
+    muonRoad.phiMiddle  = rpcFitResult.phi;
+  } else {
+    muonRoad.phiMiddle  = muonRoad.extFtfMiddlePhi;
+    rpcFitResult.phi = muonRoad.extFtfMiddlePhi;
+    rpcFitResult.phi_middle = muonRoad.extFtfMiddlePhi;
+    rpcFitResult.phi_outer = muonRoad.extFtfMiddlePhi;
+  }
   muonRoad.phiRoI     = p_roi->phi();
   muonRoad.side       = (p_roi->phi()<0.)? 0 : 1;
   muonRoad.LargeSmall = ((p_roi->sectorID() + 1)/2 )%2;
-  
+
   const int PhysicsSector = ((p_roi->sectorID() + 1)/4 )%8 + 1;
-  
+
   int special = 0;
   if (muonRoad.LargeSmall == 0 && (PhysicsSector == 6 || PhysicsSector == 8 ))
     special = 1;
   if (muonRoad.LargeSmall == 1 && (PhysicsSector == 6 || PhysicsSector == 7 ))
     special = 1;
   muonRoad.Special = special;
-  
+
   for (int i_station=0; i_station<6; i_station++) {
     for (int i_layer=0; i_layer<8; i_layer++) {
       if(!rpcFitResult.isSuccess) {
-	if (i_station==0)      muonRoad.rWidth[i_station][i_layer] = 500;//for inner
-	else if (i_station==1) muonRoad.rWidth[i_station][i_layer] = 650;//for middle
-	else if (i_station==2) muonRoad.rWidth[i_station][i_layer] = 800;//for outer
-	else if (i_station==3) muonRoad.rWidth[i_station][i_layer] = 500;//EndcapInner
-	else if (i_station==4) muonRoad.rWidth[9][i_layer] = 650;//BME
-	else if (i_station==5) muonRoad.rWidth[10][i_layer] = 650;//BMG
-	else muonRoad.rWidth[i_station][i_layer] = m_rWidth_RPC_Failed;
+	if (!insideOut){
+	  if (i_station==0)      muonRoad.rWidth[i_station][i_layer] = 500;//for inner
+	  else if (i_station==1) muonRoad.rWidth[i_station][i_layer] = 650;//for middle
+	  else if (i_station==2) muonRoad.rWidth[i_station][i_layer] = 800;//for outer
+	  else if (i_station==3) muonRoad.rWidth[i_station][i_layer] = 500;//EndcapInner
+	  else if (i_station==4) muonRoad.rWidth[9][i_layer] = 650;//BME
+	  else if (i_station==5) muonRoad.rWidth[10][i_layer] = 650;//BMG
+	  else muonRoad.rWidth[i_station][i_layer] = m_rWidth_RPC_Failed;
+	} else {
+	  if (i_station==0)      muonRoad.rWidth[i_station][i_layer] = 400;//for inner
+	  else if (i_station==1) muonRoad.rWidth[i_station][i_layer] = 200;//for middle
+	  else if (i_station==2) muonRoad.rWidth[i_station][i_layer] = 400;//for outer
+	  else if (i_station==3) muonRoad.rWidth[i_station][i_layer] = 400;//EndcapInner
+	  else if (i_station==4) muonRoad.rWidth[9][i_layer] = m_rWidth_RPC_Failed;//BME
+	  else if (i_station==5) muonRoad.rWidth[10][i_layer] = m_rWidth_RPC_Failed;//BMG
+	  else muonRoad.rWidth[i_station][i_layer] = m_rWidth_RPC_Failed;
+	}
       }
       else {
 	if (i_station==0)      muonRoad.rWidth[i_station][i_layer] = 400;//for inner
@@ -118,15 +138,15 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
       }
     }
   }
-  
+
   int sector_trigger = 99;
   int sector_overlap = 99;
   std::vector<Identifier> stationList;
   std::vector<IdentifierHash> mdtHashList;
-  
+
   // get sector_trigger and sector_overlap by using the region selector
   IdContext context = m_idHelperSvc->mdtIdHelper().module_context();
-  
+
   double etaMin =  p_roi->eta()-.02;
   double etaMax =  p_roi->eta()+.02;
   double phiMin = muonRoad.phiMiddle-.01;
@@ -142,21 +162,21 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
   else m_regionSelector->DetHashIDList(MDT, mdtHashList);
 
   if(roi) delete roi;
-  
+
   for( const IdentifierHash& hash : mdtHashList){
-    
+
     Identifier id;
     const int convert = m_idHelperSvc->mdtIdHelper().get_id(hash, id, &context);
 
     if(convert!=0) ATH_MSG_ERROR("problem converting hash list to id");
-    
+
     muonRoad.stationList.push_back(id);
     const int stationPhi = m_idHelperSvc->mdtIdHelper().stationPhi(id);
     std::string name = m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(id));
-    
+
     if ( name[1]=='M' && name[2]=='E' ) continue;//exclude BME
     if ( name[1]=='M' && name[2]=='G' ) continue;//exclude BMG
-    
+
     int LargeSmall = 0;
     if(name[2]=='S' || name[2]=='F' || name[2]=='G' ) LargeSmall = 1;
     const int sector = (stationPhi-1)*2 + LargeSmall;
@@ -165,16 +185,16 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
     else if(sector_trigger != sector)
       sector_overlap = sector;
   }
-  
+
   const int MDT_tr = (PhysicsSector - 1)*2 + muonRoad.LargeSmall;
   if (MDT_tr == sector_overlap) {
     sector_overlap = sector_trigger;
     sector_trigger = MDT_tr;
   }
-  
+
   muonRoad.MDT_sector_trigger = sector_trigger;
   muonRoad.MDT_sector_overlap = sector_overlap;
-  
+
   if (rpcFitResult.isSuccess) {
     for (int i_sector=0; i_sector<N_SECTOR; i_sector++) {
       muonRoad.aw[0][i_sector] = rpcFitResult.slope_inner;
@@ -190,7 +210,7 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
       muonRoad.aw[10][i_sector] = rpcFitResult.slope_middle;//BMG
       muonRoad.bw[10][i_sector] = rpcFitResult.offset_middle;
     }
-   
+
   } else {
     const double roiEtaLow = (roiEtaMinLow + roiEtaMaxLow) * 0.5;
     const double roiEtaHigh = (roiEtaMinHigh + roiEtaMaxHigh) * 0.5;
@@ -198,7 +218,7 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
     const double thetaHigh  = atan(exp(-fabs(roiEtaHigh)))*2.;
     const double awLow     = (fabs(roiEtaLow) > ZERO_LIMIT)? tan(thetaLow)*(fabs(roiEtaLow)/roiEtaLow): 0.;
     const double awHigh     = (fabs(roiEtaHigh) > ZERO_LIMIT)? tan(thetaHigh)*(fabs(roiEtaHigh)/roiEtaHigh): 0.;
-    
+
     for (int i_station=0; i_station<N_LAYER; i_station++) {
       for (int i_sector=0; i_sector<N_SECTOR; i_sector++) {
 	muonRoad.aw[i_station][i_sector] = awLow;
@@ -211,8 +231,27 @@ StatusCode TrigL2MuonSA::RpcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
     }
   }
 
+  if (insideOut) {
+    for (int i_sector=0; i_sector<N_SECTOR; i_sector++) {
+      ATH_MSG_DEBUG("Use aw_ftf and bw_ftf as aw and bw");
+      muonRoad.aw[0][i_sector]  = muonRoad.aw_ftf[0][0];
+      muonRoad.bw[0][i_sector]  = muonRoad.bw_ftf[0][0];
+      muonRoad.aw[1][i_sector]  = muonRoad.aw_ftf[1][0];
+      muonRoad.bw[1][i_sector]  = muonRoad.bw_ftf[1][0];
+      muonRoad.aw[2][i_sector]  = muonRoad.aw_ftf[2][0];
+      muonRoad.bw[2][i_sector]  = muonRoad.bw_ftf[2][0];
+      muonRoad.aw[3][i_sector]  = muonRoad.aw_ftf[3][0]; // Endcap Inner
+      muonRoad.bw[3][i_sector]  = muonRoad.bw_ftf[3][0];
+      muonRoad.aw[9][i_sector]  = muonRoad.aw_ftf[9][0];//BME
+      muonRoad.bw[9][i_sector]  = muonRoad.bw_ftf[9][0];
+      muonRoad.aw[10][i_sector] = muonRoad.aw_ftf[10][0];//BMG
+      muonRoad.bw[10][i_sector] = muonRoad.bw_ftf[10][0];
+    }
+  }
+  ATH_MSG_DEBUG("muonRoad.phiMiddle: " << muonRoad.phiMiddle);
+
   return StatusCode::SUCCESS;
 }
 
-// --------------------------------------------------------------------------------  
-// --------------------------------------------------------------------------------                  
+// --------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.h
index 3c603fce18c62ae79e71dc9b78b2b4c0792b7ad1..2d048de141ae9740fe5612126d82d20019d28797 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.h
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/RpcRoadDefiner.h
@@ -39,6 +39,7 @@ class RpcRoadDefiner: public AthAlgTool
   
  public:
   StatusCode defineRoad(const LVL1::RecMuonRoI*      p_roi,
+			const bool                   insideOut,
 			TrigL2MuonSA::MuonRoad&      muonRoad,
 			TrigL2MuonSA::RpcHits&       rpcHits,
 			ToolHandle<RpcPatFinder>*    rpcPatFinder,
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.cxx
index 5a5214a76ef95172d7f892b78b779b16834cb414..462859b0adc50bc55368baec8b99c5b630ba1fff 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.cxx
@@ -44,6 +44,7 @@ StatusCode TrigL2MuonSA::TgcRoadDefiner::initialize()
 // --------------------------------------------------------------------------------
 
 StatusCode TrigL2MuonSA::TgcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*      p_roi,
+                                                    const bool                   insideOut,
                                                     const TrigL2MuonSA::TgcHits& tgcHits,
                                                     TrigL2MuonSA::MuonRoad&      muonRoad,
                                                     TrigL2MuonSA::TgcFitResult&  tgcFitResult)
@@ -109,6 +110,8 @@ StatusCode TrigL2MuonSA::TgcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
 		  << "/" << tgcFitResult.tgcMid1[2] << "/" << tgcFitResult.tgcMid1[3]);
     ATH_MSG_DEBUG("tgcFitResult.tgcMid2[0/1/2/3]=" << tgcFitResult.tgcMid2[0] << "/" << tgcFitResult.tgcMid2[1]
 		  << "/" << tgcFitResult.tgcMid2[2] << "/" << tgcFitResult.tgcMid2[3]);
+  } else {
+    ATH_MSG_DEBUG("Skip TGC Fit due to zero-tgcHits");
   }
    
   if (tgcHits.size()>0 && !isMiddleFailure){
@@ -256,6 +259,7 @@ StatusCode TrigL2MuonSA::TgcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
     
   } else {
     // If no TGC hit are available, estimate the road from RoI
+    ATH_MSG_DEBUG("Because no TGC hits are available, estimate the road from RoI");
 
     roiEta = p_roi->eta();
     theta  = atan(exp(-fabs(roiEta)))*2.;
@@ -367,7 +371,30 @@ StatusCode TrigL2MuonSA::TgcRoadDefiner::defineRoad(const LVL1::RecMuonRoI*
   
   muonRoad.MDT_sector_trigger = sector_trigger;
   muonRoad.MDT_sector_overlap = sector_overlap;
-  
+
+  if (insideOut) {
+    muonRoad.side      = (muonRoad.extFtfMiddleEta<0.)? 0 : 1;
+    muonRoad.phiMiddle =  muonRoad.extFtfMiddlePhi;
+    muonRoad.phiRoI    = p_roi->phi();
+    for (int i_sector=0; i_sector<N_SECTOR; i_sector++) {
+      ATH_MSG_DEBUG("Use aw_ftf and bw_ftf as aw and bw");
+      muonRoad.aw[endcap_inner][i_sector]  = muonRoad.aw_ftf[3][0];
+      muonRoad.bw[endcap_inner][i_sector]  = muonRoad.bw_ftf[3][0];
+      muonRoad.aw[endcap_middle][i_sector] = muonRoad.aw_ftf[4][0];
+      muonRoad.bw[endcap_middle][i_sector] = muonRoad.bw_ftf[4][0];
+      muonRoad.aw[endcap_outer][i_sector]  = muonRoad.aw_ftf[5][0];
+      muonRoad.bw[endcap_outer][i_sector]  = muonRoad.bw_ftf[5][0];
+      muonRoad.aw[endcap_extra][i_sector]  = muonRoad.aw_ftf[6][0];
+      muonRoad.bw[endcap_extra][i_sector]  = muonRoad.bw_ftf[6][0];
+      muonRoad.aw[csc][i_sector]           = muonRoad.aw_ftf[7][0];
+      muonRoad.bw[csc][i_sector]           = muonRoad.bw_ftf[7][0];
+      muonRoad.aw[bee][i_sector]           = muonRoad.aw_ftf[8][0];
+      muonRoad.bw[bee][i_sector]           = muonRoad.bw_ftf[8][0];
+      muonRoad.aw[barrel_inner][i_sector]  = muonRoad.aw_ftf[0][0];
+      muonRoad.bw[barrel_inner][i_sector]  = muonRoad.bw_ftf[0][0];
+    }
+  }
+
   //
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.h b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.h
index 8fd29389e19853009373d030187c333cc8d944a1..0ee78135ca39ca997e13dcd93396c6c19cf6223a 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.h
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/TgcRoadDefiner.h
@@ -37,6 +37,7 @@ class TgcRoadDefiner: public AthAlgTool
   virtual StatusCode initialize() override;
 
   StatusCode defineRoad(const LVL1::RecMuonRoI*      p_roi,
+                        const bool                   insideOut,
                         const TrigL2MuonSA::TgcHits& tgcHits,
                         TrigL2MuonSA::MuonRoad&      muonRoad,
                         TrigL2MuonSA::TgcFitResult&  tgcFitResult);
diff --git a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/components/TrigL2MuonSA_entries.cxx b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/components/TrigL2MuonSA_entries.cxx
index 10c3af10287b52745eb632654e78fe502bd9675d..38c7cb7e3d0043a0189b6db42142a47c7594214c 100644
--- a/Trigger/TrigAlgorithms/TrigL2MuonSA/src/components/TrigL2MuonSA_entries.cxx
+++ b/Trigger/TrigAlgorithms/TrigL2MuonSA/src/components/TrigL2MuonSA_entries.cxx
@@ -31,6 +31,7 @@
 #include "../MmDataPreparator.h"
 #include "../NswPatternFinder.h"
 #include "../NswStationFitter.h"
+#include "../FtfRoadDefiner.h"
 
 using namespace TrigL2MuonSA;
 
@@ -63,6 +64,7 @@ DECLARE_COMPONENT( StgcDataPreparator )
 DECLARE_COMPONENT( MmDataPreparator )
 DECLARE_COMPONENT( NswPatternFinder )
 DECLARE_COMPONENT( NswStationFitter )
+DECLARE_COMPONENT( FtfRoadDefiner )
 
 DECLARE_COMPONENT( PtBarrelLUTSvc )
 DECLARE_COMPONENT( PtEndcapLUTSvc )
diff --git a/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.cxx b/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.cxx
index 62385efd4f6d8bf42820ccb70b32f0690be7fa2e..4cfa79340b39e4f44a3cb36b24f565ce52276122 100644
--- a/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.cxx
+++ b/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.cxx
@@ -1,12 +1,13 @@
 /*
   Filter chains for muon trigger algorithms. Designed to pass if at least one active chain is not in the list to be filtered.
   
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "MuonChainFilterAlg.h"
 #include "TrigCompositeUtils/HLTIdentifier.h"
 #include "xAODTrigMuon/L2CombinedMuonAuxContainer.h"
+#include "xAODTrigMuon/L2StandAloneMuonAuxContainer.h"
 
 MuonChainFilterAlg::MuonChainFilterAlg(const std::string& name, ISvcLocator* pSvcLocator )
 :AthAlgorithm(name, pSvcLocator)
@@ -19,6 +20,12 @@ StatusCode MuonChainFilterAlg::initialize(){
 
   ATH_CHECK(m_inputDecisionKeys.initialize());
   ATH_CHECK(m_muCombKey.initialize(m_writeL2muComb));
+  ATH_CHECK(m_muFastKey.initialize(m_writeL2muFast));
+  if ( m_filterChains.size()!=0 ) {
+    for (size_t i=0; i<m_filterChains.size(); ++i) {
+      ATH_MSG_DEBUG("IO TEST: " << i << " filter chains >> " << m_filterChains[i]);
+    }
+  }
   return StatusCode::SUCCESS;
 }
 
@@ -80,6 +87,11 @@ StatusCode MuonChainFilterAlg::execute()
     SG::WriteHandle wh_muons(m_muCombKey);
     ATH_CHECK( wh_muons.record (std::make_unique<xAOD::L2CombinedMuonContainer>(), std::make_unique<xAOD::L2CombinedMuonAuxContainer>()) );
   }
+  //write out empty muFast container since edm creator expects the container to always be present in the view
+  if(!pass && m_writeL2muFast){
+    SG::WriteHandle wh_muons(m_muFastKey);
+    ATH_CHECK( wh_muons.record (std::make_unique<xAOD::L2StandAloneMuonContainer>(), std::make_unique<xAOD::L2StandAloneMuonAuxContainer>()) );
+  }
   setFilterPassed(pass);
 
   return StatusCode::SUCCESS;
diff --git a/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.h b/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.h
index 63aaa7db4a08fae356c6b12ab19161feb1e6e44b..40bf4c4370386d52c26a01f6e7aa4580cf3fcf62 100644
--- a/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.h
+++ b/Trigger/TrigAlgorithms/TrigMuonEF/src/MuonChainFilterAlg.h
@@ -1,7 +1,7 @@
 /*
   Filter to deselect chains for muon trigger algorithms
   
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TRIGMUONEF_MUONCHAINFILTERALG_H
@@ -11,6 +11,7 @@
 #include "StoreGate/ReadHandleKeyArray.h"
 #include "TrigCompositeUtils/TrigCompositeUtils.h"
 #include "xAODTrigMuon/L2CombinedMuonContainer.h"
+#include "xAODTrigMuon/L2StandAloneMuonContainer.h"
 
 class MuonChainFilterAlg : public AthAlgorithm
 {
@@ -32,10 +33,14 @@ class MuonChainFilterAlg : public AthAlgorithm
   private :
 
     Gaudi::Property< std::vector<std::string> > m_filterChains {this, "ChainsToFilter", { }, "Vector of chains to filter out" };
-    Gaudi::Property< bool > m_writeL2muComb {this, "WriteMuComb", true, "Flag to record muComb muons" };
+    Gaudi::Property< bool > m_writeL2muComb {this, "WriteMuComb", false, "Flag to record muComb muons" };
+
     SG::ReadHandleKeyArray<TrigCompositeUtils::DecisionContainer>  m_inputDecisionKeys{ this, "InputDecisions", {}, "Inputs to the filter" };
     SG::WriteHandleKey<xAOD::L2CombinedMuonContainer> m_muCombKey {this, "L2MuCombContainer", "MuonL2CBInfo", "Output container for muComb"};
 
+    Gaudi::Property< bool > m_writeL2muFast {this, "WriteMuFast", false, "Flag to record muFast muons" };
+    SG::WriteHandleKey<xAOD::L2StandAloneMuonContainer> m_muFastKey {this, "L2MuFastContainer", "MuonL2SAInfo", "Output container for muFast"};
+
 };
 
 #endif
diff --git a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
index 788bfe7baec49da30b526fef949224dc54d53fce..550c094fc9800a57137ae92481619d75d1a68f7f 100644
--- a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
+++ b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
@@ -230,9 +230,15 @@ TriggerHLTListRun3 = [
     ('xAOD::L2StandAloneMuonContainer#HLT_MuonL2SAInfo',        'BS ESD AODFULL', 'Muon', 'inViews:MUViewRoIs'),
     ('xAOD::L2StandAloneMuonAuxContainer#HLT_MuonL2SAInfoAux.', 'BS ESD AODFULL', 'Muon'),
 
+    ('xAOD::L2StandAloneMuonContainer#HLT_MuonL2SAInfoIOmode',        'BS ESD AODFULL', 'Muon', 'inViews:MUCombViewRoIs'),
+    ('xAOD::L2StandAloneMuonAuxContainer#HLT_MuonL2SAInfoIOmodeAux.', 'BS ESD AODFULL', 'Muon'),
+
     ('xAOD::L2CombinedMuonContainer#HLT_MuonL2CBInfo',          'BS ESD AODFULL', 'Muon', 'inViews:MUCombViewRoIs'),
     ('xAOD::L2CombinedMuonAuxContainer#HLT_MuonL2CBInfoAux.',   'BS ESD AODFULL', 'Muon'),
 
+    ('xAOD::L2CombinedMuonContainer#HLT_MuonL2CBInfoIOmode',          'BS ESD AODFULL', 'Muon', 'inViews:MUCombViewRoIs'),
+    ('xAOD::L2CombinedMuonAuxContainer#HLT_MuonL2CBInfoIOmodeAux.',   'BS ESD AODFULL', 'Muon'),
+
     ('xAOD::L2IsoMuonContainer#HLT_MuonL2ISInfo',               'BS ESD AODFULL', 'Muon', 'inViews:MUIsoViewRoIs'),
     ('xAOD::L2IsoMuonAuxContainer#HLT_MuonL2ISInfoAux.',        'BS ESD AODFULL', 'Muon'),
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
index 8629344668e98cb3d10fce03a2dd083fbc0894f5..021839f81493d60dc4ba67997424f239370c3061 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
@@ -260,6 +260,9 @@ def setupMenu():
     ]
 
     TriggerFlags.BphysicsSlice.signatures = TriggerFlags.BphysicsSlice.signatures() + [
+        ChainProp(name='HLT_mu4_l2io_L1MU4', groups=SingleMuonGroup),
+        ChainProp(name='HLT_2mu14_l2io_L12MU10', groups=MultiMuonGroup),
+        ChainProp(name='HLT_2mu6_l2io_L12MU6',     l1SeedThresholds=['MU6'],   groups=MultiMuonGroup),
         #ATR-20603
         ChainProp(name='HLT_2mu4_bJpsimumu_L12MU4', groups=BphysicsGroup),
         ChainProp(name='HLT_2mu4_bUpsimumu_L12MU4', groups=BphysicsGroup),
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py
index 84ef904afa5e8e5c08d947c5801a4b0d2b8e1a44..5caab332213d20697a84e5e9b7641fbdc3c03411 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py
@@ -192,7 +192,7 @@ MuonChainParts = {
     'trigType'       : ['mu'],
     'etaRange'       : ['0eta2550','0eta105'],
     'threshold'      : '',
-    'extra'          : ['noL1', 'Comb', 'fast', 'msonly','lateMu', "Dr", "muoncalib"],
+    'extra'          : ['noL1', 'Comb', 'fast', 'msonly','lateMu', "Dr", "muoncalib" ,'l2io'],
     'IDinfo'         : [],
     'isoInfo'        : ['ivar','ivarmedium'],
     'invMassInfo'    : ['10invm70'],
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py
index 824a4e6adac8e9293e0be0dd38c5c14983ec51c6..f80aea431a2c557fac5e39c16c60ac17f1398b0e 100755
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py
@@ -11,7 +11,7 @@ log = logging.getLogger("TriggerMenuMT.HLTMenuConfig.Muon.MuonDef")
 
 from TriggerMenuMT.HLTMenuConfig.Menu.ChainConfigurationBase import ChainConfigurationBase
 
-from TriggerMenuMT.HLTMenuConfig.Muon.MuonSequenceSetup import muFastSequence, muFastOvlpRmSequence, muCombSequence, muCombOvlpRmSequence, muEFSASequence, muIsoSequence, muEFCBSequence, muEFSAFSSequence, muEFCBFSSequence, muEFIsoSequence, efLateMuRoISequence, efLateMuSequence
+from TriggerMenuMT.HLTMenuConfig.Muon.MuonSequenceSetup import muFastSequence, muFastOvlpRmSequence, muCombSequence, muCombOvlpRmSequence, mul2IOOvlpRmSequence, muEFSASequence, muIsoSequence, muEFCBSequence, muEFSAFSSequence, muEFCBFSSequence, muEFIsoSequence, efLateMuRoISequence, efLateMuSequence
 from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigMuonEFInvMassHypoToolFromDict
 
 # this must be moved to the HypoTool file:
@@ -38,6 +38,9 @@ def muCombSequenceCfg(flags):
 def muCombOvlpRmSequenceCfg(flags):
     return muCombOvlpRmSequence()
 
+def mul2IOOvlpRmSequenceCfg(flags):
+    return mul2IOOvlpRmSequence()
+
 def muEFSASequenceCfg(flags):
     return muEFSASequence()
 
@@ -107,6 +110,7 @@ class MuonChainConfiguration(ChainConfigurationBase):
             "":[['getmuFast', 'getmuComb'], ['getmuEFSA', 'getmuEFCB']],
             "fast":[['getmuFast']],
             "Comb":[['getmuFast', 'getmuComb']],
+            "l2io":[['getmuFast', 'getmuComb'], ['getmuEFSA', 'getmuEFCB']],
             "noL2Comb" : [['getmuFast'], ['getmuEFSA', 'getmuEFCB']],
             "ivar":[['getmuFast', 'getmuComb', 'getmuIso']],
             "noL1":[[],['getFSmuEFSA', 'getFSmuEFCB']],
@@ -123,7 +127,7 @@ class MuonChainConfiguration(ChainConfigurationBase):
     # --------------------
     def getmuFast(self):
         doOvlpRm = False
-        if "bTau" in self.chainName or "bJpsi" in self.chainName or "bUpsi" in self.chainName or "bDimu" in self.chainName or "bBmu" in self.chainName:
+        if "bTau" in self.chainName or "bJpsi" in self.chainName or "bUpsi" in self.chainName or "bDimu" in self.chainName or "bBmu" in self.chainName or "l2io" in self.chainName:
            doOvlpRm = False
         elif self.mult>1:
            doOvlpRm = True
@@ -149,6 +153,12 @@ class MuonChainConfiguration(ChainConfigurationBase):
         else:
            doOvlpRm = False
 
+        doL2ioOvlpRm = False
+        if "l2io" in self.chainName:
+            doL2ioOvlpRm = True
+        if doL2ioOvlpRm:
+            return self.getStep(2, 'muComb', [mul2IOOvlpRmSequenceCfg] )
+
         if doOvlpRm:
            return self.getStep(2, 'muComb', [muCombOvlpRmSequenceCfg] )
         else:
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py
index 48997c2a26c8f293dfefeb32d47e88215af9c804..629c628fc2e2a599caf895ca887076f588d8f4d7 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py
@@ -115,7 +115,7 @@ def muCombAlgSequence(ConfigFlags):
     l2muCombViewsMaker.ViewFallThrough = True #if this needs to access anything from the previous step, from within the view
 
     ### get ID tracking and muComb reco sequences ###    
-    from TriggerMenuMT.HLTMenuConfig.Muon.MuonSetup  import muCombRecoSequence, muonIDFastTrackingSequence
+    from TriggerMenuMT.HLTMenuConfig.Muon.MuonSetup  import muFastRecoSequence, muCombRecoSequence, muonIDFastTrackingSequence
     muCombRecoSequence, sequenceOut = muCombRecoSequence( l2muCombViewsMaker.InViewRoIs, "FTF" )
  
     #Filter algorithm to run muComb only if non-Bphysics muon chains are active
@@ -126,7 +126,13 @@ def muCombAlgSequence(ConfigFlags):
     muonChainFilter.ChainsToFilter=bphysChains
     muonChainFilter.InputDecisions = [ CFNaming.inputMakerOutName(l2muCombViewsMaker.name()) ]
     muonChainFilter.L2MuCombContainer = sequenceOut
+    muonChainFilter.WriteMuFast = False
+    muonChainFilter.WriteMuComb = True
+    # Debug for L2IO
+    from AthenaCommon.Constants import DEBUG
+    muonChainFilter.OutputLevel = DEBUG
 
+    # for nominal muComb
     muCombFilterSequence = seqAND("l2muCombFilterSequence", [muonChainFilter, muCombRecoSequence])
 
     extraLoads = []
@@ -140,7 +146,24 @@ def muCombAlgSequence(ConfigFlags):
       extraLoads += [( 'xAOD::TrigCompositeContainer' , 'StoreGateSvc+'+decision )]
 
     muFastIDRecoSequence = muonIDFastTrackingSequence( l2muCombViewsMaker.InViewRoIs , "", extraLoads )
-    muCombIDSequence = parOR("l2muCombIDSequence", [muFastIDRecoSequence, muCombFilterSequence])
+    # muCombIDSequence = parOR("l2muCombIDSequence", [muFastIDRecoSequence, muCombFilterSequence])
+
+    # for Inside-out L2SA
+    muFastIORecoSequence, sequenceOutL2SAIO = muFastRecoSequence( "MURoIs", doFullScanID=False, InsideOutMode=True )
+    insideoutMuonChainFilter = MuonChainFilterAlg("FilterInsideOutMuonChains")
+    insideoutMuonChains = getInsideOutMuonChainNames()
+    insideoutMuonChainFilter.ChainsToFilter = insideoutMuonChains
+    insideoutMuonChainFilter.InputDecisions = [ CFNaming.inputMakerOutName(l2muCombViewsMaker.name()) ]
+    insideoutMuonChainFilter.L2MuFastContainer = sequenceOutL2SAIO
+    insideoutMuonChainFilter.WriteMuFast = True
+    insideoutMuonChainFilter.WriteMuComb = False
+    # Debug for L2IO
+    from AthenaCommon.Constants import DEBUG
+    insideoutMuonChainFilter.OutputLevel = DEBUG
+
+    muFastIOFilterSequence = seqAND("l2muFastIOFilterSequence", [insideoutMuonChainFilter, muFastIORecoSequence])
+
+    muCombIDSequence = parOR("l2muCombIDSequence", [muFastIDRecoSequence, muCombFilterSequence, muFastIOFilterSequence])
 
     l2muCombViewsMaker.ViewNodeName = muCombIDSequence.name()
 
@@ -187,6 +210,30 @@ def muCombOvlpRmSequence():
 
 
 
+def mul2IOOvlpRmSequence():
+
+    (l2muCombSequence, l2muCombViewsMaker, sequenceOut) = RecoFragmentsPool.retrieve(muCombAlgSequence, ConfigFlags)
+
+    ### set up muCombHypo algorithm ###
+    from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigmuCombHypoAlg
+    trigmuCombHypo = TrigmuCombHypoAlg("TrigL2MuCBIOHypoAlg")
+    trigmuCombHypo.MuonL2CBInfoFromMuCombAlg = muNames.L2CBName+"IOmode"
+
+    ### set up L2muOverlapRemoval ###
+    # from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigL2MuonOverlapRemoverMucombAlg
+    # trigL2MuonOverlapRemover = TrigL2MuonOverlapRemoverMucombAlg("TrigL2MuonIOOverlapRemoverMucombAlg")
+    # trigL2MuonOverlapRemover.L2MuonOverlapInfoFromMuCombAlg = muNames.L2CBName+"IOmode"
+
+    # from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigL2MuonOverlapRemoverMucombToolFromDict
+    from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigmuCombHypoToolwORFromDict
+
+    return MenuSequence( Sequence    = l2muCombSequence,
+                         Maker       = l2muCombViewsMaker,
+                         Hypo        = trigmuCombHypo,
+                         HypoToolGen = TrigmuCombHypoToolwORFromDict )
+
+
+
 ######################
 ###  EFSA step ###
 ######################
@@ -605,3 +652,24 @@ def getBphysChainNames():
         for chain in bphysSlice:
             chains.append(chain.name)
     return chains
+
+############################################################
+### Get muon triggers except L2 inside-out trigger
+### to filter chains where we don't want to run L2SA IO mode
+############################################################
+
+def getInsideOutMuonChainNames():
+
+    from TriggerJobOpts.TriggerFlags import TriggerFlags
+    muonSlice = TriggerFlags.MuonSlice.signatures()
+    bphysSlice = TriggerFlags.BphysicsSlice.signatures()
+    chains =[]
+    if muonSlice:
+        for chain in muonSlice:
+            if "l2io" not in chain.name:
+                chains.append(chain.name)
+    if bphysSlice:
+        for chain in bphysSlice:
+            if "l2io" not in chain.name:
+                chains.append(chain.name)
+    return chains
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSetup.py
index 6fcebe53a7efa7981972043531bc92d4940c1c42..a04acce209a24154c683b83c1cdf840df8f2511b 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSetup.py
@@ -335,12 +335,33 @@ def makeMuonPrepDataAlgs(RoIs="MURoIs", forFullScan=False):
   return muDecodeRecoSequence
 
 
-def muFastRecoSequence( RoIs, doFullScanID = False ):
+def muFastRecoSequence( RoIs, doFullScanID = False, InsideOutMode=False ):
 
   from AthenaCommon.AppMgr import ToolSvc
   from AthenaCommon.CFElements import parOR
 
-  muFastRecoSequence = parOR("l2MuViewNode")
+  # muFastRecoSequence = parOR("l2MuViewNode")
+  postFix = ""
+  if InsideOutMode:
+    postFix = "IOmode"
+  muFastRecoSequence = parOR("l2Mu"+postFix+"ViewNode")
+
+  # In insideout mode, need to inherit muon decoding objects for TGC, RPC, MDT, CSC
+  if InsideOutMode:
+    import AthenaCommon.CfgMgr as CfgMgr
+    ViewVerify = CfgMgr.AthViews__ViewDataVerifier("muFastIOmodeViewDataVerifier")
+    ViewVerify.DataObjects = [('Muon::TgcPrepDataContainer','StoreGateSvc+TGC_Measurements'),
+                              ('TgcRdoContainer' , 'StoreGateSvc+TGCRDO'),
+                              ('Muon::RpcPrepDataContainer','StoreGateSvc+RPC_Measurements'),
+                              ('Muon::MdtPrepDataContainer','StoreGateSvc+MDT_DriftCircles'),
+                              ('TrigRoiDescriptorCollection','StoreGateSvc+MURoIs')]
+    if MuonGeometryFlags.hasCSC():
+      ViewVerify.DataObjects += [('Muon::CscPrepDataContainer','StoreGateSvc+CSC_Clusters')]
+    if MuonGeometryFlags.hasSTGC():
+      ViewVerify.DataObjects += [('Muon::sTgcPrepDataContainer','StoreGateSvc+STGC_Measurements')]
+    if MuonGeometryFlags.hasMM():
+      ViewVerify.DataObjects += [('Muon::MMPrepDataContainer','StoreGateSvc+MM_Measurements')]
+    muFastRecoSequence+=ViewVerify
 
   import AthenaCommon.CfgMgr as CfgMgr
   muFastRecoVDV = CfgMgr.AthViews__ViewDataVerifier("muFastRecoVDV")
@@ -427,7 +448,7 @@ def muFastRecoSequence( RoIs, doFullScanID = False ):
 
   ### set up MuFastSteering ###
   from TrigL2MuonSA.TrigL2MuonSAConfig import TrigL2MuonSAMTConfig
-  muFastAlg = TrigL2MuonSAMTConfig("Muon")
+  muFastAlg = TrigL2MuonSAMTConfig("Muon"+postFix)
 
   from TrigL2MuonSA.TrigL2MuonSAConf import TrigL2MuonSA__MuFastDataPreparator
   MuFastDataPreparator = TrigL2MuonSA__MuFastDataPreparator()
@@ -451,11 +472,43 @@ def muFastRecoSequence( RoIs, doFullScanID = False ):
 
   muFastAlg.RecMuonRoI = "HLT_RecMURoIs"
   muFastAlg.MuRoIs = RoIs
-  muFastAlg.MuonL2SAInfo = muNames.L2SAName
-  muFastAlg.MuonCalibrationStream = "MuonCalibrationStream"
-  muFastAlg.forID = muNames.L2forIDName
-  muFastAlg.forMS = "forMS" 
+  muFastAlg.MuonL2SAInfo = muNames.L2SAName+postFix
+  muFastAlg.L2IOCB = muNames.L2CBName+postFix
+  muFastAlg.MuonCalibrationStream = "MuonCalibrationStream"+postFix
+  muFastAlg.forID = muNames.L2forIDName+postFix
+  muFastAlg.forMS = "forMS"+postFix
   muFastAlg.FILL_FSIDRoI = doFullScanID
+  muFastAlg.InsideOutMode = InsideOutMode
+  muFastAlg.TrackParticlesContainerName = TrackParticlesName
+
+  # Debug for L2IO
+  from AthenaCommon.Constants import DEBUG, INFO
+  muFastAlg.OutputLevel = DEBUG
+  muFastAlg.DataPreparator.OutputLevel = DEBUG
+  muFastAlg.PatternFinder.OutputLevel = DEBUG
+  muFastAlg.StationFitter.OutputLevel = DEBUG
+  muFastAlg.TrackFitter.OutputLevel = DEBUG
+  muFastAlg.TrackExtrapolator.OutputLevel = DEBUG
+  muFastAlg.BackExtrapolator.OutputLevel = DEBUG
+  muFastAlg.CalibrationStreamer.OutputLevel = DEBUG
+  muFastAlg.CscSegmentMaker.OutputLevel = DEBUG
+  muFastAlg.MonTool.OutputLevel = INFO
+  from TrigL2MuonSA.TrigL2MuonSAConf import TrigL2MuonSA__RpcRoadDefiner
+  rpc_roaddefiner = TrigL2MuonSA__RpcRoadDefiner()
+  rpc_roaddefiner.OutputLevel = DEBUG
+  ToolSvc += rpc_roaddefiner
+  from TrigL2MuonSA.TrigL2MuonSAConf import TrigL2MuonSA__RpcPatFinder
+  rpc_patfinder = TrigL2MuonSA__RpcPatFinder()
+  rpc_patfinder.OutputLevel = DEBUG
+  ToolSvc += rpc_patfinder
+  from TrigL2MuonSA.TrigL2MuonSAConf import TrigL2MuonSA__TgcRoadDefiner
+  tgc_roaddefiner = TrigL2MuonSA__TgcRoadDefiner()
+  tgc_roaddefiner.OutputLevel = DEBUG
+  ToolSvc += tgc_roaddefiner
+  from TrigL2MuonSA.TrigL2MuonSAConf import TrigL2MuonSA__RpcDataPreparator
+  rpc_datapreparator = TrigL2MuonSA__RpcDataPreparator()
+  rpc_datapreparator.OutputLevel = DEBUG
+  ToolSvc += rpc_datapreparator
 
   muFastRecoSequence += muFastAlg
   sequenceOut = muFastAlg.MuonL2SAInfo