def controller_loss(x, net, print_loss=False, use_nominal=False, use_eq=None, loss_coeff=1e-8):
    """
    Compute a loss to train the filtered controller

    args:
        x: the points at which to evaluate the loss
        net: a CLF_CBF_QP_Net instance
        print_loss: True to enable printing the values of component terms
        use_nominal: if True, compare u_learned to nominal. If false, just penalize norm of u
    returns:
        loss: the loss for the given controller function
    """
    u_learned, _, _, _ = net(x)
    u_learned = u_learned.squeeze()

    if use_nominal:
        # Compute loss based on difference from nominal controller (e.g. LQR).
        u_nominal = net.u_nominal(x, **net.nominal_scenario)
        controller_squared_error = loss_coeff * ((u_nominal - u_learned)**2).sum(dim=-1)
    elif use_eq is not None:
        # compute loss based on difference from equilibrium control
        u_eq = net.u_nominal(use_eq, **net.nominal_scenario)
        controller_squared_error = loss_coeff * ((u_eq - u_learned)**2).sum(dim=-1)
    else:
        controller_squared_error = loss_coeff * (u_learned**2).sum(dim=-1)
    loss = controller_squared_error.mean()

    if print_loss:
        print(f"                controller term: {controller_squared_error.mean().item()}")

    return loss