class_docstr: TorchModelV2 concat'ing CNN outputs to flat input(s), followed by FC(s).
  
  Note: This model should be used for complex (Dict or Tuple) observation
  spaces that have one or more image components.
  
  The data flow is as follows:
  
  `obs` (e.g. Tuple[img0, img1, discrete0]) -> `CNN0 + CNN1 + ONE-HOT`
  `CNN0 + CNN1 + ONE-HOT` -> concat all flat outputs -> `out`
  `out` -> (optional) FC-stack -> `out2`
  `out2` -> action (logits) and value heads.
class_docstr_tok: ["TorchModelV2","concat'ing","CNN","outputs","to","flat","input","(","s",")",",","followed","by","FC","(","s",")",".","Note",":","This","model","should","be","used","for","complex","(","Dict","or","Tuple",")","observation","spaces","that","have","one","or","more","image","components",".","The","data","flow","is","as","follows",":","`","obs","`","(","e.g",".","Tuple","[","img0",",","img1",",","discrete0","]",")","-",">","`","CNN0","+","CNN1","+","ONE-HOT","`","`","CNN0","+","CNN1","+","ONE-HOT","`","-",">","concat","all","flat","outputs","-",">","`","out","`","`","out","`","-",">","(","optional",")","FC-stack","-",">","`","out2","`","`","out2","`","-",">","action","(","logits",")","and","value","heads","."]
code: def forward(self, input_dict, state, seq_lens):
      if SampleBatch.OBS in input_dict and "obs_flat" in input_dict:
          orig_obs = input_dict[SampleBatch.OBS]
      else:
          orig_obs = restore_original_dimensions(
              input_dict[SampleBatch.OBS],
              self.processed_obs_space,
              tensorlib="torch",
          )
      # Push observations through the different components
      # (CNNs, one-hot + FC, etc..).
      outs = []
      for i, component in enumerate(tree.flatten(orig_obs)):
          i = str(i)
          if i in self.cnns:
              cnn_out, _ = self.cnns[i](
                  SampleBatch({SampleBatch.OBS: component})
              )
              outs.append(cnn_out)
          elif i in self.one_hot:
              if component.dtype in [
                  torch.int8,
                  torch.int16,
                  torch.int32,
                  torch.int64,
                  torch.uint8,
              ]:
                  one_hot_in = {
                      SampleBatch.OBS: one_hot(
                          component, self.flattened_input_space[int(i)]
                      )
                  }
              else:
                  one_hot_in = {SampleBatch.OBS: component}
              one_hot_out, _ = self.one_hot[i](SampleBatch(one_hot_in))
              outs.append(one_hot_out)
          else:
              nn_out, _ = self.flatten[i](
                  SampleBatch(
                      {
                          SampleBatch.OBS: torch.reshape(
                              component, [-1, self.flatten_dims[i]]
                          )
                      }
                  )
              )
              outs.append(nn_out)
  
      # Concat all outputs and the non-image inputs.
      out = torch.cat(outs, dim=1)
      # Push through (optional) FC-stack (this may be an empty stack).
      out, _ = self.post_fc_stack(SampleBatch({SampleBatch.OBS: out}))
  
      # No logits/value branches.
      if self.logits_layer is None:
          return out, []
  
      # Logits- and value branches.
      logits, values = self.logits_layer(out), self.value_layer(out)
      self._value_out = torch.reshape(values, [-1])
      return logits, []
  
file_path: ray/python/ray/rllib/models/torch/complex_input_net.py
imports: from gymnasium.spaces import Box, Discrete, MultiDiscrete
  import numpy
  import tree
  from ray.rllib.models.torch.misc import normc_initializer, SlimFC
  from ray.rllib.models.catalog import ModelCatalog
  from ray.rllib.models.modelv2 import ModelV2, restore_original_dimensions
  from ray.rllib.models.torch.torch_modelv2 import TorchModelV2
  from ray.rllib.models.utils import get_filter_config
  from ray.rllib.policy.sample_batch import SampleBatch
  from ray.rllib.utils.annotations import override
  from ray.rllib.utils.framework import try_import_torch
  from ray.rllib.utils.spaces.space_utils import flatten_space
  from ray.rllib.utils.torch_utils import one_hot
label_desc: Use image node_id 2 for calling the ComplexInputNetwork obj's underlying member method code with example usage: obj.forward(input_dict, state, seq_lens) and returns: logits,  list, out,  list