Conveyor Simulation

I’m using setTargetVelocity on static objects to simulate conveyors. When the box rides along one conveyor and then slides onto a second conveyor running at a higher speed the transfer doesn’t work quite right.

The box’s velocity stays at the slower speed (matching the first conveyor’s target) until the box has completely cleared that conveyor. Once it is no longer contacting that conveyor it accelerates to the speed of the second conveyor.

However, if the box falls so that it contacts both conveyors at the same time then it works as expected accelerating gradually as it transfers from one conveyor to the other reaching the speed of the second conveyor after it fully transfers off of the first conveyor.

Any advice on how to debug this?

added video from PVD showing 1 box landing on both conveyors and transferring correctly and one box landing fully on one conveyor

conveyor speed increase.GIF

Thanks for reporting the issue.

Would you be able to provide a code snippet showing how you set up your scene?

If not possible, could you please provide the PVD capture so we can recreate the exact set-up from your scene?

Thanks for the response.

The code for this is just a quick modification of the SnippetHelloWorld example. I’ll try to attach the cpp file.
SnippetHelloWorld.cpp (9.35 KB)

Thanks. I’ll take a look at this now and see if I can get to the bottom of what you’re reporting

My initial findings suggest that this might not be incorrect results. AFAICT, the solver is doing what should be the correct thing.

Friction force causes the box to be moved in the direction of the conveyor belt. Frictional force is proportional to normal force and the majority of the normal force is applied by the slower conveyor belt, meaning it applies more friction than the second, faster belt.

The reasons are as follows:

Until the COM of the box is transferred to the second belt, the whole mass of the box is supported by the first, slower belt so, even when there’s a little bit of the box on the second conveyor, until the whole thing transfers, it applies very little normal force, so therefore very little friction. Once the COM transfers, part of the mass is still supported by the slower belt because it happens to be the first constraint that is processed by the solver (if the second belt was the first pair processed, it may work slightly better, but only slightly).

One of the issues is that, when the box accelerates forwards due to the conveyor effect, there is a subtle weight transfer to the rear contacts to combat any rolling effect caused by the frictional acceleration (think how a ball would roll on the conveyor belt - the box naturally does something similar but the contacts at the rear of the box (always in contact with the conveyor belt) apply a relatively large normal force to compensate for this rolling effect). This means that the majority of the weight will usually be on the rear contacts and it probably wouldn’t accelerate much until a lot of the box transferred to the other conveyor belt. You may be able to shift the COM of the box slightly to compensate for this but I wasn’t able to get much of an improvement by trying this.

The reason the other box transfers more smoothly is potentially because it bounces a little just as it is transferring from one conveyor to another. I verified that this didn’t change the order that the constraints are processed in so the only explanation I can offer is that the subtle weight transfer maybe hadn’t happened to the same degree. Given a more even weight distribution between the conveyor belts, the second belt manages to accelerate the box more.

Does this sound reasonable?

Yeah those are all important points about what’s going on but they don’t seem to be enough to explain the results. There seems to be something more at play.
Checking the linear velocity reported in PVD, the box only gets to 1.01m/s until it completely loses contact with the slower conveyor. That negligible acceleration would not appear to be sufficient to increase the force on the rear contacts significantly. The first conveyor’s contacts seem to completely overwhelm the forces applied by the second conveyor’s contacts.

To check this, using only one box, I reversed the order of the conveyors so the box lands on the 2m/s belt and then transfers onto the 1m/s belt. In that case, the deceleration should place additional force on the second conveyor and I would expect the box’s deceleration profile to be a mirror of the acceleration. That was partially true. The box changed speed a little bit sooner under deceleration than it did under acceleration but it only managed to get down to 1.7m/s and it did that only in the last few frames where that the contact existed. There seems to be something else causing the first conveyor to have a much higher influence on the box than the second conveyor.

The only thing I can think of in the real world that would make the box prefer its first speed is inertia. So I changed the box density from 10 down to 0.1 and increased the friction from 0.2 to 0.95. In the acceleration scenario, this had almost no effect. On the other hand, in the deceleration scenario, it did cause decel to happen sooner - just a little after the COM transfer.

It seems to my uneducated eye, that there’s still something in how the constraints are processed that is causing variations in the behavior.

How did you see the order of the constraints? I assume that this order can’t be influenced from my program?

I will try changing the number of iterations next. Can you think of any other settings that could influence this?

thanks again

So out of the scenarios I tried in my previous post, the one that seem to behave closest to what I would expect was high friction, low mass and deceleration. One thing that was peculiar to that scenario was that the box bounced a little bit when it started to contact the second conveyor.

Perhaps I should be using a shape with rounded corners because the sharp corners seem to have a big effect when sliding from one surface to another even though the 2 surfaces are in the same plane.

Anyway, this observation is kind of similar to the one in my original post, the box that bounced while contacting the second conveyor seems to respond to forces from both conveyors in contact with it while where there’s no bounce the first conveyor’s forces overwhelm the second.

Solver position iterations does have an effect. At 10 iterations the box starts to accelerate 0.1m earlier and at 250 iterations the box starts to accelerate 0.5m earlier. The box being 2m in length, it is still well past the COM before beginning to accelerate even at 250 iterations.

I’ll revisit this again (probably next week) but I couldn’t find any indication of a bug.

The constraint solver was processing all the correct constraints and attempting to drive to both a target velocity of 1 and a target velocity of 2. The normal force applied to resolve the contacts were significantly smaller with the faster conveyor than the slower conveyor, so the friction with the slower conveyor was stronger and resulted in the velocity only slightly increasing until it was completely transferred to the faster conveyor. Friction force is in the range -un <= f <= un, where u = friction coefficient and n = normal force, so given an object resting on 2 surfaces moving at different speeds, friction will always be strongest on the surface that applies the most normal force.

When the box is accelerating on the conveyor, the frictional force pushing it forwards causes an angular velocity that is resisted by the rear contacts. This means there is more normal force applied through the rear contacts than the front contacts while accelerating. Once the box reaches the target speed, the frictional force tends towards zero and the normal forces become more evenly distributed.

When the box reaches the faster conveyor, the weight is supported more-or-less entirely by the first conveyor until the COM transfers - as I mentioned, if a coin was flipped and the faster conveyor was processed first, the results may be ever-so-slightly different but, after a few iterations, it would converge on a similar result for reasons described in the next paragraph. You don’t have control over the order that pairs are processed - it just comes down to how they come from the island manager, which is generally the order in which the pairs were created. While there are differences in behaviour if the constraints are reordered, there generally isn’t a single “correct” answer with complex N-body physics scenarios. However, with gauss-seidel style solvers, the constraints that are solved later have the ability to overpower those solved earlier in the iteration (last word wins), so this is actually the case where, if it were possible, the faster conveyor should have won if there was a 50/50 battle.

As more of the box transfers to the faster conveyor, there is increasing normal force with the faster conveyor on the front contacts. However, the acceleration from increased friction causes an angular velocity which causes the normal force to shift to the rear contacts on the slower conveyor and decrease on the front contacts (on the faster box). The rear contacts allow an increased amount of friction (driving towards a velocity of 1). There’s a back-and-forth struggle between the front and rear contacts because normal force from the rear contacts and frictional deceleration from the rear contacts also causes some angular velocity that moves some of the normal force back to the front contacts. This will be why more iterations seems to cause acceleration to occur a little earlier. However, the result seems to consistently be that there is more normal force on the rear contacts and its friction holds strong until the box has more-or-less completely transferred to the faster conveyor.

As far as I can tell, this is all physically fairly accurate.

Thanks for your attention on this, your explanations have been helpful.

The part that doesn’t make sense to me is: I’d expect the box to accelerate some amount even before COM transfers because there is some force applied by the faster contacts. Even with a lot of iterations, acceleration only starts after the box is 3/4 transferred. If all or most of that difference was to be explained by the rotational forces of acceleration then when we switch to deceleration we would see a big difference in where the box changes speed but the difference is quite small.

And of course, how a little bounce at just the right time seems change the whole dynamic.

I understand where you are coming from.

The friction force required to maintain the 1m/s velocity on the conveyor is very small once the box gets to that speed, so the friction with the slower conveyor belt is far from the limit where it will slip. For every small amount of friction force applied by the contacts with the faster conveyor, the slower conveyor applies an equal and opposing force because friction constraints are equality constraints - aiming to make the relative velocity at the contact exactly whatever the target velocity is. There is a limit to how much force they can apply - this is u*n, where u is the friction coefficient and n is the normal force. As the normal force is larger with the contacts on the slower conveyor, it can apply more friction force than the faster belt, so the faster belt hits its limit before the slower belt does.

The bounce that makes it produce the result you expected is interesting but not unexpected. Once the box accelerates to a given speed, it requires less force to maintain current speed than change it given that an object in a vacuum will maintain its velocity unless it is acted on by a force, and at these speeds air resistance (or damping) would be negligible. It probably just takes a few frames with the faster conveyor ‘winning’ and it would be the slower conveyor that is stuck fighting the losing battle against momentum.

Even if the normal force was the same on both the slower and faster conveyor, we’d just see friction roughly cancel each other out and the overall speed would maintain roughly the same. The faster conveyor’s contacts can only cause an acceleration if they can apply more.friction than the slower conveyor’s contacts, which doesn’t happen until a large portion of the box is supported by the faster conveyor due to the small rotation I mentioned earlier.

You probably could get the effect you want by increasing friction on the faster conveyor belt.

Please see this video at 1m06 (can’t figure out how to copy a link at a particular time in the video on my phone). It shows the effect you’re seeing in real life

I will play with the friction coefficients to try to modify the behavior a little bit. It won’t be as simple as giving the downstream conveyor a higher friction material since I’m planning to build a system with a large number of conveyors but I imagine with a little logic in the contact modify callback I can influence how the box transfers from one belt to another.

One other question for you: you’ve been talking about the specific forces applied by the different contacts and you even seem to have some insight into what logic generated them. I imagine some of that you can infer based on your knowledge of the code but are there tools I can learn to inspect those things? At one point I tried printing the contact impulse values in the onContact callback but while I could see the y component as the box landed and then steadily oppose gravity, the z component (direction of the target velocity) was always 0. Maybe because the the modified target velocity gets added to the calculation at a later step?

Any tips or resources I could read to learn how to inspect this would be appreciated.

Thanks again for your clear explanations. I wasn’t sure what to expect posting in these forums but I’m impressed with the quality responses.

PhysX currently reports normal force, but not friction force. Depending on friction model used, friction may not be applied per-contact but instead using a friction patch which can include up to 4 friction constraints. This system includes a correlation approach that tracks and corrects numerical drift so you don’t get continuous small friction drift that is common in some other physics engines. Unfortunately, this means debugging friction involves breakpointing or instrumenting the solver. It seems quite likely that we will add reports for friction force relatively soon because I expect this will end up being useful for robotics applications. So far, it hasn’t been requested by game developers afaik.

Ok, I tried some different friction coefficients and I’m back.

I set all the materials to 0.01.

Then in the contact modify callback I set the friction to 0.99 for all contacts that are on my faster conveyor.

The low friction contact meant that it took a couple meters of travel to accelerate to 1m/s after contacting the first conveyor. But then it still stuck stubbornly at 1m/s until the COM transferred to the faster and grippier conveyor. It started to accelerate a few cm before dead center and then it accelerated fairly quickly reaching the speed of the second conveyor a few cm past dead center.

Hi kstorey,
Just checking in again because I remember you mentioned you’d try to find time to have another look at this.

The youtube video you found showing boxes accelerating quite late into the transfer was instructive but that was just one example. Under different scenarios (longer boxes, grippier conveyors, etc) we will have different results.

Changing friction coefficients like in my last comment has such a tiny effect. That makes me think there might be something that could be optimized to be more realistic in the solver and it also leaves me without many tools to influence this behavior into something that looks more correct to me.

Any more info you might have for me would be much appreciated - or if you’re unable to spend any more time on this issue I’d appreciate knowing that too.