So I've found this to be an intriguing problem, and have ended up giving it quite a bit of thought over the past 24 hours. I think my solution somewhat builds on Scouting Ninja's advice.
I'll go back to what I said earlier in that probably the easiest way to do this for you may be to animate it in Blender or whatever animation program you use. Unreal (or Unity) almost certainly has a way to load in non-humanoid (because there's plenty of tutorials on doing basically the same thing with a humanoid armature) and it's animation data and play it back. Then you should just need to control the playback speed. That's skinned animation even though this is a rigid model. For artists, that's almost certain to be the easy way out and I expect it would work just fine.
The programmer side of me wanted this to be rigged animation instead. That requires understanding that bones are actually matrices and a little matrix algebra. I come from a background with XNA and then DX11 and OGL 4.5. There you have to use matrices everywhere. So, in an engine like Unity (where I've seen this) and probably in Unreal a lot of that is obfuscated from you and you are just presented with position, orientation, and scale without realizing that that's basically a game matrix. So, it may not even occur to most to treat them as matrices. But that's exactly what I would do.
The thing that makes this tricky is the "main rod" of the engine. For this discussion I will be using the part names from this picture. The main rod is a problem because one end is attached to the piston rod at the crosshead. The other end is attached to the side rod on the main crankpin which is attached to the driving wheel (unlabeled but that's the wheel being turned most directly by the engine). In the real world, that crankpin is going to move in a circular path because of real world physics and the fact that it is basically on a circular track (the wheel). You don't have real world physics here, so you have to basically simulate what's going on and therein is the primary problem. Additionally, the side rod drives the other two wheels on that side.
It helps substantially here if you've done rigged animation with matrices before, because this is one of the most complex examples of it I've ever done and it helps tremendously if you've done it with something a bit more simple to get the concept down.
But the way rigged animation works is that when you multiply two matrices together the result parent's one matrix to the other. So, you substitute the result of that multiplication for the child's matrix. To start off with, you need to parent the train body to everything else mathematically. You can do that in Blender, for example, as long as the engine reads and understands that relationship when it imports the model. Even if it doesn't you can parent objects in Unreal (or Unity) and it will do the same thing. Or if you could not do that (which you can) you could even do it mathematically yourself by getting a matrix for the parent, maintaining your own matrix for the child, multiplying the two together every draw frame and putting the result matrix back into the child for it's position, orientation, and scale. But I think if you just get these relationships right in Unreal, it will take care of about 80% of the work for you.
So, the locomotive body would be the main parent (great great grandparent or such depending on how deep this goes because children can be parents too). Everything would be a child of that. Once you do this, all of those parts will be attached to the body and move with it although they will not be yet animated. Moving the piston rod is easy; because of the parent-child relationship, it's position is relative to the locomotive and it simply needs to move forwards and backwards at a calculated rate dependent on the locomotive's velocity. (You'll have to do some math there although you can probably "wing" some of the math and just do what looks right.) The first big problem is that the main rod doesn't just simply move back and forth, but rather one end travels in a circle.
I think the way I would solve this is to have the wheels actually disconnected from that and animate them separately. The wheels would be children of the locomotive body. And if you rotate them, they should be attached to the same spot on the body while rotating like wheel's should. You just have to figure out the circumference of the wheel and rotate the wheel 2pi (360 degrees) every time the locomotive moves that distance. All the wheels will turn at the same rate as long as they are the same diameter/circumference.
And here's the key: I would put the crankpins on the wheels as children of the wheel. That would give it an actual position relative to the wheel it is a child of. That's not so you can animate the crankpin or attach anything to it; this is just a simulation of reality. It's because you need a position to point at. And the solution is that the main rod's bone (a bone is a matrix basically) is centered at the crosshead. The main rod must have it's position at the crosshead for this to work right. So, when you talk about the main rod's position you are also talking about the position of the crosshead. That makes that long rod controlled there at the crosshead. Now, all you need to do is use a LookAt() function for the main rod's orientation/rotation and have it "look at" the main crankpin. As long as all the speeds are right, that should basically keep it attached to the main crankpin. And viola!
I think the primary problem left is the side rod; it needs to stay horizontal as it travels through it's circular path. There are probably several ways to handle this. You could have it as a child of the front crankpin and do a LookAt() to the back crankpin.
So, that's your main motion. If you get into the motions of the other rods, it should basically be more of the same.
Hope that helps!