I don’t know how in depth you want me to go but here’s some useful info:
I was trying to learn the angle as an output of a network so instead of learning one value I instead learned 2 values corresponding to two components of the rotation matrix about z (R_z(φ) in this helpful guide 43).
I then recovered the angle using equation 3 in the same link above which corresponds to atan(sin(φ),cos(φ)).
So I learned sin(φ) and cos(φ) (which lay in the range (-1,1) using a hardtanh activation function,
(torch.nn.Hardtanh(min_val=-1,max_val=1),
and then recovered the angle using,
torch.atan2(sin(φ),cos(φ))
This gave the resulting angle back in the range (-180,180) degrees so you have to be careful and make sure your sin(φ) and cos(φ) which come out at  the end of the network are in the range (-1,1).
I hope that helps! As for a loss function I simply used mean squared error loss and it works beautifully.