docs: def geodetic2ecef(lat: float, lon: float, alt: float,
                    ell: Ellipsoid = None, deg: bool = True) -> Tuple[float, float, float]:
      """
      point transformation from Geodetic of specified ellipsoid (default WGS-84) to ECEF
  
      Parameters
      ----------
  
      lat : float or numpy.ndarray of float
             target geodetic latitude
      lon : float or numpy.ndarray of float
             target geodetic longitude
      h : float or numpy.ndarray of float
           target altitude above geodetic ellipsoid (meters)
      ell : Ellipsoid, optional
            reference ellipsoid
      deg : bool, optional
            degrees input/output  (False: radians in/out)
  
  
      Returns
      -------
  
      ECEF (Earth centered, Earth fixed)  x,y,z
  
      x : float or numpy.ndarray of float
          target x ECEF coordinate (meters)
      y : float or numpy.ndarray of float
          target y ECEF coordinate (meters)
      z : float or numpy.ndarray of float
          target z ECEF coordinate (meters)
      """
      if ell is None:
          ell = Ellipsoid()
  
      if deg:
          lat = radians(lat)
          lon = radians(lon)
  
      with np.errstate(invalid='ignore'):
          # need np.any() to handle scalar and array cases
          if np.any((lat < -pi / 2) | (lat > pi / 2)):
              raise ValueError('-90 <= lat <= 90')
  
      # radius of curvature of the prime vertical section
      N = get_radius_normal(lat, ell)
      # Compute cartesian (geocentric) coordinates given  (curvilinear) geodetic
      # coordinates.
      x = (N + alt) * cos(lat) * cos(lon)
      y = (N + alt) * cos(lat) * sin(lon)
      z = (N * (ell.b / ell.a)**2 + alt) * sin(lat)
  
      return x, y, z