[OPEN-SOURCE] Machinery Modelling Toolkit

Hi, I’ve been playing around with your plugin for a few weeks and I have to say it’s awesome! I followed guide to get my first tank up and running using the M113 model. I used your movement, tracks and suspension and inherited all that behavior from MMPawn into my own tank base class that contained some basic AI & Turret/Barrel movement etc. This worked really well, my classes were able to run on top of your MMPawn class without any issues besides a few variable renaming.

I am now trying to make an Abrams tank but use the T26 base instead of the M113. I think I’m really close to having it hooked (I think) but there’s no guide so I’ve been trying and failing until something works. There’s some weird behavior that I am not sure what it could be. I am going to outline my process I used so far first and then present the weird behavior. It’s likely something super simple, but I’ve been looking and I can’t seem to see it.

So I chose to use the ModularDriveTrainV2 to base the Abrams tank off of. Reason for this was because the suspension implemented in the example was “somewhat” close to what I would need (it didn’t have the little suspension pieces that the T26 normally does at the bottom) and I thought that removing the modular drive and replacing it with the arcade movement would be easier than the other way around if I had chosen to base it off LightTankPureBP. I’m not sure if this was the right call.

This is what I ended up with after removing the modular drive, adding wheels ( to make them fit I just scaled the entire wheel hierarchy to 2.1/2.1/2.1, not sure if this is wrong vs using the linear limit or something (linear limit is set to 15 right now)) and adding all the necessary array elements to update TrackAnimationDriveR / TrackAnimationDriveL.

Front view after adding the physics wheels and updating splines:

TrackAnimationDriveR/L:

RoadWheelPhys01R (Static Mesh Component):

RoadWheelTAF01R ( Track Anisotropic Friction):

RoadWheelPhys01PCR ( Physics Constraint Component):

UpdateFriction / ResetFriction functions updated:


To update the functions above and the Event Graph below I copied the way LightTankPureBP was implemented.

Event Graph:

The movement/input portion of the top of the event graph looks just like LightTankPureBP, I did not want to add 4 more pictures just to cover this as it’s identical.

I also added six (one for each new wheel ) of the OnComponentHit nodes:

I think those are all the adjustments I made so far (I think, it’s hard to remember back to all the minor changes I made along the way but those should be the main ones) and in view port this is what the tracks look like:

PROBLEM:

However, when I press play and possess the vehicle the wheels and track act really strange and I’m having a difficult time figuring out where I screwed up. Basically, the wheels are jittery, they do not line up correctly and the track goes all crazy. The tank moves ever so slightly if I hold down the throttle but for the most part the wheels just spin and the tank stays in place. I feel like there’s a fundamental lack of understanding of the principles behind the physics involved here that I’m not getting so I am not able to configure it right. This is what it looks like, the spockets and wheels spin, the track moves as well but as you can see not exactly correctly:

Any help is appreciated! It would be nice it this could turn this into a short “how to guide” to better understand how to utilize your new implementations with various different chassis types and wheel configurations. Again, this is an amazing plugin and I just want to thank you again for your contribution, cheers.

@kensai01
There are two principally different ways how suspension of the tank can be setup in MMT - rigid body physics wheels with constraints or “traces” suspension. As far as I see, you are using rigid body wheels. This was old approach I’ve experimented with and later switched to traced suspension. The main reason is because I couldn’t avoid small jittering of the wheels even when everything is setup correctly. Another issue is performance impact - constraints and rigid bodies are quite expensive compared to raytraces or sweeps.

Anyway, as you have it setup already, it makes sense to try this approach.
It looks lovely is you are using old friction components and this has to be changed. But first, disable friction calculations and check if suspension works correctly - maybe wheels collide with each other or constraint force is too weak/strong.

To disable collision between wheels, select all physics wheels with cntrl (blue wireframe meshes), open Collision Preset in Collision tab and set their Object Type to wheels, make sure that in the list of collision channels Wheels and Chassis are set to Ignore. This way physics wheels should just clip through each other and chassis without collision.

So I will do this one step at a time to see any changes each step makes. I removed the collision from the wheels and it seems to have fixed the jitteryness / misalignment of the wheels. The track is still screwed up. Here’s what it looks like now after just changing the collision tab of the physics wheels:

I’m now going to start working on replacing the old friction components, can you elaborate a bit more on that? I saw a few pages back a post on how to set up Anisotropic Traction, is that what you are referring to - if so, would following those posts be what I would need to do? I will try that & play with it myself and report back.

Side note, when I press the forward button, all the wheels turn but some are turning clockwise and others counter clockwise, I don’t see any particular pattern. I assume I just need to orient them correctly on their axis so they all face the right way. I’m going to look into this as well now.

**Tracks **
The issue with track is in which spline points of the track are binding to which wheels. If you are using TrackAnimationDrive component then settings look like this:
c69900430cf715a93fd4d67ca10c42d088ce932a.jpeg

If you are using new component - MMT Track Animation Component then settings are these:
93a179caba39a32f071bd67d0ee89b343564e20d.jpeg

So what you need to do is set proper spline point index and name of the physical wheel it should be using. If you look at how splines are made on example vehicles, you’ll see that control points of the splines are aligned with wheels. So if your 5-th control point is under the first wheel, then you will have something like
Point Index: 4 (count starts from 0)
Mesh Name: PhysicsWheelLeft01
Socket Name: MyTreadSocket

Socket is placed on the wheel mesh itself and its offset to a position where track should pass. In case of existing meshes that you use, socket is inside of the mesh as physics mesh is thick enough to cover both roadwheel and track.

Check LightTankTraceWheelsWithAnimBPPrototype in the Land Vehicles level, as example of how to use new track animation component (MMT Track Animation Component), which is improved and ported to c++ version of previous component.

Friction
What you need is MMTFrictionComponent - it’s a an optimized c++ implementation of the old BP code with plenty of fixes and issues solved. The usage is very similar to old component but as example you can use LightTankTraceWheelsWithAnimBPPrototype. It uses raytraces for roadwheels but Sprocket and Idler are using rigid bodies, just as in your setup. So you will use OnComponentHit events to pass contact information to friction component.

Roadwheels rotation
Most likely some of the wheels are rotated 180 degrees or “Flip Rotation” is set to true (or should be set to true) in TrackAnimationDrive component. You can see that option on the screenshots above.

Update

Added Anti-roll bar support for Suspension Stack component.
Anti-roll force is not calculated inside of the component but in BP that communicates between suspension stacks on the same axis:

AntiRollRatio is clamped to 0…1 range, where at 0 no Anti-Roll force will be applied and at 1 there will be virtually no body rocking as full anti-roll force will be applied. Keep it lower than 1 if you want a bit more dynamic driving experience (vehicle tilting in turns) or set it to 1 if you need a perfectly balanced suspension.

The function itself uses suspension forces of each individual stack and Anti-Roll ratio to calculate appropriate anti-roll force:
6ebbf1632a297650636b0f248536bd551a42ea9e.jpeg

Anti-roll force is applied separately from suspension force. For this to work, new function in suspension component had to be made - ApplyAntiRollForce() , so you have to use latest version of the Plugin or Content to be able to call this new function.

To see example of how it’s used check 4WheeledVehicle in LandVehicles map.

Thanks for the detailed reply. I am going to look into this now and report back. I have the spline points fixed now, it looks good so I will work on porting over the new c++ friction and animation components.

For the old ATrackedVehicle based system I have been playing with the suspension parameters and I was able to configure it in a fashion for the Abrams chassis at a weight of 60k that work really well to get over obstacles that fit under the chassis clearance but have a vertical slope such as a step. It took some playing around with the chassis collision box size and position as well as parameters. Basically, originally the tank kept getting stuck on various things in the environment and completely flip or just instantly stop and I wanted to adjust that so it could go over things that are rectangular easily.


Notice that the first and last wheel on each side have a larger collision radius than the inner wheels. ie. 1st & 7th wheel have a collision radius of 47 and the rest have a collision radius of 43. This helped with going over rectangular bumps.

8110d85b2cfd2b678c3987f52ec9136cd5238ec3.jpeg Notice the tank weight of 60k, fairly accurate for the Abrams I think.

I trimmed the collision box (green line) so that the front didn’t collide before the wheels, this seemed to have a big effect. (In reality, I am not sure if the blue imported collision box is being used too so I don’t know if I even need the green collision box but that’s besides the point)

Here’s how it drives now over some rectangular objects:
[video][/video]

I’m really happy with the way it looks now, some more tweaking needed but generally it performs great!

I made some progress but I’m a bit stuck again. I updated the spline points so the track draws correctly now.

I then swapped out all the wheels with the same implementation that was used for the Idler/Sprocket of the LightTankTraceWheelsWithAnimBPPrototype. I also ported all the functions into blueprint from the LightTankTraceWheelsWithAnimBPPrototype that were related but not the ones that set up the suspension system as I was not using it. The track correctly spins but the wheels do not move, tank does not move either.

TrackAnimationDriver (new MMTTrack Animation Comp.) parameters, the animated spline points and track spline points have all been updated:
028a33deac2b604ed6518c7b03efca12654f1de8.jpeg

RoadWheels Friction component added to all wheels ( new MMTFriction Comp.):
028a33deac2b604ed6518c7b03efca12654f1de8.jpeg

I made a quick video showing my steps, all the various components parameters and blueprints I updated rather than post a bunch of screen captures. Let me know if that works well for you, I feel bad asking a bunch of questions.

Video of the conversion process:

Forgot to show in video, Updated OnHitComponents:

Video of track spinning & wheels not spinning:

I feel like I’m relatively close to getting it working, my instinct tells me that maybe I should be using the new suspension stack but it seems it needs a skeletal animation. Anyhow, I’ll continue working on this over the next few days but I have to stop for now so I wanted to show where I’m at.

@kensai01 Don’t worry, you can ask as many question as you want and I’ll do my best to answer them. This system is work in progress and I know that it’s not obvious how it can be used and which parts are responsible for what. Questions are like feedback - they help me to understand how people interact with the system and it provides insight on what should be changed and improved.

Just to clarify, suspension components don’t require skeletal meshes or static meshes. Each suspension component calculates position of the center of the wheel and then this information can be retrieved and used with static/skeletal meshes, but it doesn’t have too. T-26 (Light Tank) uses skeletal mesh to animate movement of bogies, animation is driven by positions of roadwheels and their position is calculated by suspension component. As another example, look at 4WheeledVehicle example, it uses the same suspension components as Light Tank but has just a single wheel with collision (used for shape sweeps). Visual wheels are just set into position calculated in suspension component.

I see couple of issues in your screenshots/video:

  1. Register Friction Point - this function notifies friction component that there is some contact point with ground or another object and this contact need to be processed. There are two cases when this function is used: on collision events and with suspension components. In your case, as rigid bodies with physics constraints are used, only on collision events case is relevant. Then it’s important to have “Treat as Impulse” flag of RegisterFrictionPoint as TRUE because collision force is reported as impulse (Normal Impulse). This flag is set to false when suspension component is used as suspension force is reported as force, not as impulse.

  2. To get wheels/sprocker/idler rotating you have 2 options:
    a) if your wheels and sprocket are static meshes (not part of the skeletal mesh) you can add them into array of first parameter in TrackAnimationDriver, called “Sprockets Idlers Roadwheels”, you can see it in your screenshots. Then TrackAnimationDrive component should animate them automatically when it updates animation of the track
    b) in case if you use skeletal mesh (wheels/sprocket/idler are parts of the skeletal mesh), then rotation information have to be manually passed into Animation Blueprint. For this, you can retrieve current angle of rotation of the sprocket from TrackAnimationDrive. This is what T-26 (Light Tank) is using to animate it’s wheels/sprocket/idler

  3. I suspect that you have collision problems because of how springs/drives of physics constraints are working. I see in the video that tank has a very high clearance, compared to what it has in real life. I had the same problem with old version of T-26 that was build using constraints.
    What is happening is following. You have some limits of how far constraint body is allowed to travel along one of the axis, in relation to some starting point. When body is not moving anywhere and sits next to starting point, spring force is 0. When body is getting closer to the limit of allowed movement, spring force raises linearly until it reaches “Linear Drive Force” that you set as parameter of physics constraint. The problem with this setup is that you need to have some amount of suspension force to hold tank above the ground but it’s not clear when you get this force. In theory, if you set “Linear Drive Force” twice of what is needed to hold the tank, then you should get desired amount of force at 50% compression of the suspension. Which means that your suspension travel distance have to be larger than it is on the real tank. In case of double suspension force it needs to be twice the size.
    So what if we set “Linear Drive Force” three or four times higher than what we need to hold tank? We can do that and we will get require amount of force at 1/3rd or 1/4th of suspension compression, which means we can have a shorter suspension travel (closer to reality). Unfortunately this will have a downside - what if suspension compresses to 90% because tank is going over an obstacle? You will get too much suspension force. If you suspension even more stiff, like 10x required minimal force, it can send tank flying into the air.
    The solution to this I’ve implemented in Suspension Stack component. Where spring compression is non-linear and you get required force just after 1cm of compression. After initial compression, force goes up to a user defined value (2-3x higher than required force). This allows to have a precise amount of clearance and stiffness of the suspension. Unfortunately, Suspension Stack currently doesn’t work with rigid bodies but I’m planning to add this ability in feature.

  4. Track Spline Point Locations and Track Spline Point Tangents are optional in new TrackAnimationDrive component. You can edit your spline directly in BP and component will use it as a template for animation. This was not possible in past and this is why those arrays are still there.

My conclusion is that “Treat as Impulse” flag of RegisterFrictionPoint is the issue here which prevents tank from driving forward.

Thanks for the detailed reply, it was very informative. Based on your paragraph about suspension systems working multiple ways and after reviewing the 4WheeledVehicle blueprint I decided to scrap my current progress and restart by duplicating the LightTank and reworking it’s suspension to match the Abrams. This worked really well. Here’s the process if anyone else is interested:

I started with LightTankTraceWheelsWithAnimBP, first I immediately removed the skeletal suspension and disconnected the corresponding blueprint links then retested - it still drove. Next I removed the sway links and the corresponding blueprint links, tank still drove.

Then I began setting up the tank:
Overview:


Idler, Sprocket setup:
In order, Idler Physics Static Mesh, Idler Physics Constraint, MMFriction Component, Static Mesh for the visual of the wheel.

Current Suspension Setup (this is the same for all 14 suspension spots):
MMTSuspension Stack Component, Static Mesh for physics, MMTFriction Component, Static Mesh for the visual of the wheel

Track Animation Left: (right Y value for Track Spline Point Locations for me is 144)

At this point the suspension works and the tracks move correctly, however the wheels did not move up and down with the suspension. So I looked for inspiration in the 4TrackedVehicle and moved over the UpdateWheelPosition function and combined all 14 of them into a UpdateWheelPositions function…

At this point I only have one slight problem, the wheels sit inside of the track when I drive as such, any advise as to what to adjust would be helpful:

UPDATE: Fixed the wheel alignment problem by updating the physics mesh to the other available front/back facing styles, now the wheels align property:

The only issue is that this seems to cause me to get stuck a bit going up steep inclines as such:

I’m glad you got it working!

I would just re-model collision meshes, similar to what is installed on LightTank. Just make them bigger and place pivot point in such a way that it aligns with center of the wheel. Check LightTank example again - you will see that pivot of PhysicalWheelMesh and VisualWheels align. The meshes that you use right now, are missing “tail” which should help with sliding over obstacle from one wheel collision to another. These “tails” and angled “fronts” help to imitate track tension.
But even if alignment is not perfect, it should have enough power to drive over the obstacle. As LightTank can scale vertical walls:
[video]https://youtu.be/b-hcoQV-WiQ?t=18[/video]
(on 18-th second)

I’ve spotted three things on your screenshots:

  1. Friction settings are different on sprocket and track - shouldn’t cause issues, it possible to use it like that, just be aware of it.
  2. Spring Output Ratio on Suspension Stack component is set to 1.05. If this is default value then its my mistake, it should be higher, like at least 2.0-2.5. Otherwise your suspension on one of the side might not have enough force to hold full mass of vehicle, which shouldn’t happen as chassis will collide with the ground.
  3. Suspension stack offset is from 80 to -65, which is 80+65cm - quite a lot for the tank. Bottom offset should be just 1cm lower than your maximum allowed wheels droop, which on tanks is usually not too large. It’s fine to make it just 1cm lower than your “static” wheel position (when tank is standing on ground). Just need to have proper amount of Spring Stiffness. Which is:
    Minimal Spring Stiffness = Mass Of Tank * 980 / total number of wheels with suspension
    In reality it won’t match perfectly as center of mass of the chassis is most likely not exactly in the middle of the vehicle, but this number is a good stating guess.

Btw, most of the new components have tooltips for each variable and setting, they might help. Not sure if you’ve seen them, they don’t show up immediately.

Hi Bored Engineer.

I am building a more simplified version of your tank physics for the game i am making. I am using the plugin so i can do sub-stepping for my physics.
I have got the tank working how i want except for a few small issues.

One issue that i am having is that when my vehicle comes to a stop it keeps making small little slides because the friction i am applying is reactionary.
Another issue that i am having is that when my tank lands at high speeds it will clip through the ground then bounce back up. I think this may be because i am using my suspension previous length to position the wheels and tracks.
And another issue i have is if i set my frame rate to be limited, the springs will bounce more. This means if i set it low to like 10 fps then the tank will go shooting off into space.

Do you have any ideas of what i can do to fix these issues and if you need it, what code would you like me to post a screenshot of.

Everything was working fine but now I am having some issues again, spent most of today trying to figure this out with no luck so far. It’s a really WEIRD problem because I have no clue how I could have caused it. Basically, I was working on getting some basic multiplayer working and part of that was starting the steam subsystem. After creating a few menus and wanting to test a level I went back and all my tanks are now with most of the suspension submerged like in the picture above. The tracks don’t spin anymore nor does the tank want to move forward. Only thing it does is lightly vibrate and pop up a tiny bit as it vibrates forward, very very slowly.

However, if I place a tank from your pack that was NOT re-parented to my base class it works fine - so only tanks that inherit MMTPawn -> TrackedVehicle -> Blueprint implementation cause an issue but anything that goes directly from MMTPawn -> blueprint implementation works just fine. I’m blown away because it was working fine as early as earlier today and now I can’t seem to figure out at all what I could have possibly done.

If anyone has experienced something similar or anyone has any ideas, please let me know!

UPDATE: I reverted the changes to the build that enabled Steam and the suspensions work again. I’m now looking into why enabling Steam broke the suspension… Apparently I followed an out-dated guide as the way the steam subsystem is initialized changed over the past few versions of the game engine. This caused the game to not load the plugin. Following https://docs.unrealengine.com/latest/INT/Programming/Online/Steam/#iniconfiguration worked fine as far as initializing the system goes.

Filter your force or velocity to which you react. Simple average over last two frame worked well in my case.

No idea on this.

Sounds like you are not using sub-stepping. It’s not enough to enable it, you have to do your calculations in sub-step “ticks” and use rigid bodies true position in calculations.

Haven’t used Steam with UE4, but did had such issue when transitioning to 4.16 and plugin was not loading.

So would this be say to get the velocity and the previous velocity and then doing a mean of the 2 and replacing where the current velocity was used?

I am using sub-stepping for my physics and using the mmt transforms.

This image shows that I am using the mmt sub-stepping tick.

This image show my suspension code. Can you see what is causing the extra suspension force at low fps. The green line coming from the bottom left is the sub-step delta time and the transform is from an mmt get transfrom node.

Yeap, that’s what I do currently. You can try the same with resulting force, haven’t tried it yet.

Looks fine to me. Is sub-stepping enabled in project settings?

Ohh wait, you need to use MMT’s Add Force too, default one doesn’t work from inside of sub-stepping.

Yeap, that’s what I do currently. You can try the same with resulting force, haven’t tried it yet.
[/QUOTE]

I have tried this and it now slides very slowly constantly in on direction sideways. In the forward direction the vehicle I imagine it is the same but something with my vehicle means that it keeps accelerating forwards with a small force. This means if i stop the tank it will then stat to accelerate forwards very slowly.

Ohh wait, you need to use MMT’s Add Force too, default one doesn’t work from inside of sub-stepping.
[/QUOTE]

Yeah that was it!. Works now. All my others were fine but i forgot to make this one mmt.

On horizontal surface or slope? If on horizontal then either center of mass is too much to one side or suspension is not apply equal force. You can counter-act one with another.
On slope it’s more complicated, you can check what I do in MMT on light tank and 4 Wheeled Vehicle - spawn constraint when wheels/tracks are not spinning and controls are not pressed. Then break constraint when either one happens. Constraint is breakable, so it breaks if something pushes vehicle externally. It’s not ideal solution.

I moved the centre of mass of my tank back and that means that it now stays still moving forwards but the horizontal sliding is still there. I noticed on the mmt add force node there is a change velocity box. With this box could I get it so that i can get the velocity and then change the velocity in the other direction to keep the vehicle still?

I was investigating what happens of slopes when i noticed that if i climb a slope with my tank facing in the +x axis then it will hit the slope, slow down and go back down and will never get to the top but if i go a a slope facing in the -x axis then it goes up like it is flat but then when I turn my vehicle to the side it will shoot off the slope at a ludicrous speed. What do you think is causing this?