Hi Chrono developers,
We are using Chrono 10.0.0, ChSystemNSC with the Bullet collision backend, and while validating a rigid wheel on a flat box we found what appears to be an axis inconsistency in the cylindrical-shell collision path.
ChCollisionShapeCylindricalShell publicly defines the shell axis as local Z, and the internal Bullet shell also appears to use Z. However, cbtCylshellBoxCollisionAlgorithm uses the transformed Y axis (getColumn(1)), and in Chrono 10.0.0 cbtCylindricalShellShape::getHalfLength() also reads Y rather than Z.
We built four isolated Chrono 10.0.0 variants from official commit 9faf13dd8f1128dd75ed233a9627027b0422c3f7, with identical public geometry:
For a cylindrical shell with radius 70 mm, width 30 mm, local Z aligned with the physical horizontal wheel axle, on a flat box:
So the axis change clearly fixes the zero-tilt contact geometry.
However, S3 still does not produce robust dynamic wheel contact:
We also noticed that current upstream appears to have changed the half-length accessor to Z, while the custom shell-box algorithm still appears to select Y.
Our questions are:
We have a minimal standalone reproducer and the exact S0/S1/S2/S3 diffs/results and can provide them.
Thanks.
Hi Kirill,
Apologies that this sat for so long. You are right on both counts, and I have checked it against today's main rather than 10.0.0.
The shell's axis is Z throughout the shape: the public header says so, the Bullet shell is built with half extents (radius, radius, half height), its support function reads the half height from Z, and the collision model injects it with no rotation. The shell-box algorithm nevertheless reads the axis from column 1, which is Y, and that is a bug. Your other finding, getHalfLength reading Y, which for this shape returns the radius rather than the half height, was fixed on main on 8 August as a side effect of the rounded-shapes work, which is why upstream now has a correct half length and a wrong axis. Your S1 and S2 results fall out of that exactly: fixing the half length alone narrowed the shell while the axis was still wrong, and fixing the axis alone worked because the wrong half length was the radius, which is larger than the true half width and hid the error.
So that this does not fall through the cracks again, I opened an issue with both parts, the axis bug and the question your S3 results raise about whether this algorithm is meant to carry a rolling wheel at all:
https://github.com/projectchrono/chrono/issues/848
Two requests. Please attach your reproducer and the S0 to S3 diffs there, since they make the case better than anything I can write. And if you are willing, open the pull request for the axis line yourself. You found it and bisected it, and the credit should be yours; your last fix went in the same day.
On your practical questions 4 and 5. The S3 numbers, contact present on roughly half the steps on a flat face, are not a tuning problem. The algorithm's own header says it replaces the shell with a capsule per box direction and may produce zero, one or two contacts, so intermittent contact on a plane is built into the method. Whether it should be improved or documented as not for wheels is a call for the maintainers, and the issue asks them. For your rigid wheel today, use what the vehicle code itself uses on Bullet: a ChCollisionShapeCylinder, which goes through Bullet's standard convex machinery and never touches this custom algorithm, or a triangle mesh, which is what ChRigidTire::SetContactMesh does. The cylindrical shell earns its keep in the multicore collision system, where it has its own narrowphase; that is where the demos use it as the default tire shape.
Thank you for the careful work, twice now :-)
Dan
------------------------------------------------
Robert and Laura Hensel Professor
NVIDIA CUDA Fellow
Department of Mechanical & Aerospace Engineering
Department of Electrical & Computer Engineering
Department of Computer Science
University of Wisconsin - Madison
4150ME, 1513 University Avenue
Madison, WI 53706-1572
------------------------------------------------
--
You received this message because you are subscribed to the Google Groups "ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
projectchron...@googlegroups.com.
To view this discussion visit
https://groups.google.com/d/msgid/projectchrono/7fbaeabd-bc22-4497-b51e-f698278014d3n%40googlegroups.com.
Hi Kyrill,
Sorry for joining the party so late. I meant to reply to your first query, but I was busy over the last month and only now things are calming down some (I’m still on travel for 10 more days).
You and Dan have correctly concluded that there is a bug in the current implementation of the cylindrical shell collision primitive and have a fix (I haven’t looked at that yet, but I assume it’s correct). Having said that, I’d like to step back a bit, give some context, and then ask one question.
I implemented this particular collision shape a while ago when I was looking to reduce the cost of simulating tracked vehicles; I wanted to see if using this simplified cylindrical shape (which ignores the caps) can help with efficiency by allowing a simple analytical collision detection against boxes (the main interaction between track wheels and rollers against track shoes). It turned out that the savings were not really worth it and I abandoned using it in any models and simulations. For reasons I will not get into right now, this code found its way in the main branch.
Lately, I have been culling the Chrono code for dead code and features that nobody really uses, and which only add complexity to the code and make maintenance more difficult. The cylindrical shell shape was on the chopping block. But then you posted and I said I will get back to you with this very discussion before making a decision in that regard (as I already mentioned, I got swept with other things and didn’t get a chance to do so).
The question I wanted to ask you is simply whether you really need this collision shape. If the answer is no, then my inclination would be to completely retire the shape altogether. If you have a legit application for it, we can keep it and fix it as in your PR.
From your message, I gather that you don’t particularly need this shape. Your question was if this is suitable for a rigid wheel on rigid flat terrain. The answer is *no*. You are better off using either a cylinder (you will get the exact same behavior for the side walls as with the cylindrical shell and also interaction with the caps). Even better, use a “rounded cylinder” shape; until recently, this shape was not fully implemented in Chrono. At the request of another user, I filled in the missing support for both rounded cylinders and rounded boxes. By the way, if I recall correctly, that user wanted to use rounded cylinders for the exact same type of application as you (rigid wheel on rigid terrain).
So, the bottom line is this: from where I sit, the cylindrical shell shape is not really useful, and I would prefer to obsolete it. If however, you have a good argument for keeping it, we’ll simply adopt the fix in your PR (I’d like to get a chance to look at it more carefully first). Please let me know.
Best,
Radu
From: projec...@googlegroups.com <projec...@googlegroups.com>
On Behalf Of Kirill Vorotnikov
Sent: Sunday, 13 September 2026 14:55
To: ProjectChrono <projec...@googlegroups.com>
Subject: [chrono] Chrono 10.0.0 cylindrical-shell axis mismatch fixed, but rolling shell-box contact still unstable
Hi Chrono developers,
--
Hi Radu,
Thank you - this context is very helpful!
No, we do not specifically need the cylindrical-shell collision shape. Our actual application is a rigid wheel on rigid terrain, and the shell was only investigated because we were looking for a physically appropriate wheel contact representation.
Given your explanation, I would not argue for keeping the cylindrical shell on our account. If you prefer to retire it, that is perfectly fine from our side.
Dan had suggested either a standard cylinder or a triangle contact mesh for the Bullet path. Based on your recommendation, we will now evaluate the rounded cylinder first, using the standard cylinder as a reference.
Regarding PR #853: I opened it at Dan’s request for the confirmed axis bug. I am happy to leave it open while you decide whether to keep or obsolete the shape, or close it if retiring the shape is the preferred direction.
Thanks again for taking the time to explain the history and intended use of this primitive.
Best regards,
Kirill.
Hi Kirill,
I’ll look again into this when I return from travel (mid-October) and decide then. I’ll let you know.
A triangle mesh like Dan suggested is a perfectly valid option, but I would use that only if the desired geometry cannot be described with a primitive shape (cylinder, rounded cylinder, etc). If you are interested in a wheel that is a perfect cylinder, model it as a cylinder. If capturing the tread is important, use a triangular mesh.
It’d be great if you could report back here what you find when using a rounded cylinder. I didn’t get a chance to experiment with that shape as a wheel model after completing its implementation.
--Radu
To view this discussion visit https://groups.google.com/d/msgid/projectchrono/d8572479-bab4-484c-a997-1611f5474d05n%40googlegroups.com.
Hi Radu,
I started with the rounded-cylinder option you suggested, but hit a geometry-semantics issue before running any dynamics, so I stopped there rather than guessing parameters.
For our wheel the desired external geometry is 140 mm diameter, 30 mm total width, with approximately a 5 mm edge radius.
From the current public ChCollisionShapeRoundedCylinder geometry contract, this appears to correspond to:
That gives the expected public bounding dimensions of 140 mm diameter and 30 mm width.
However, following the current Bullet conversion path on main (9e95a025... in my checkout), the same parameters appear to produce Bullet half-extents corresponding to 130 mm diameter and 20 mm width at zero envelope. Conversely, using radius = 70 mm and height = 30 mm to match the Bullet outer extents makes the public shape bounding box 150 mm × 40 mm once the 5 mm sweep is included.
So before testing contact behavior, I wanted to check the intended parameter convention:
Should radius and height describe the core cylinder, with sphere_swept added outward, or should they describe the final outer cylinder envelope with the sweep contained inside it?
I may simply be reading the new Bullet conversion incorrectly, but the public shape geometry and the Bullet support/AABB path currently appear to use different conventions.
I stopped before dynamics so I wouldn’t tune the wheel geometry around the wrong interpretation.
If useful, I can post the exact source locations and the small geometry check.
Best regards,
Kirill
Hi Kirill,
There were indeed some inconsistencies in how rounded cylinders were defined/used in different parts of the code.
I unified them into the following convention: “radius and height specify the overall (outer) size of the object with the “rounding” sradius cut into it” (that is, your last option below:
the parameters define “the final outer cylinder envelope with the sweep contained inside it”). This is also
consistent with how other shapes are defined and treated for things like the MPR narrowphase algorithm in the multicore collision detection.
So, for your desired wheel geometry, you should use radius=70, height=30, sradius=5.
There were a couple of other things I had left out during my first pass at implementing the rounded cylinder and box shapes (e.g., the volume and gyration calculations were approximated by those of the skeleton shape) which are now fixed.
Then, I asked Claude to generate a unit test. See utest_COLL_rounded_shapes.
The code is available in the ‘main’ branch. Please let me know if you find any other issues with these two shapes.
--Radu
To view this discussion visit https://groups.google.com/d/msgid/projectchrono/15c5713b-a19e-44cd-ba64-93cd29ccec72n%40googlegroups.com.
Hi Radu,
Thanks again. I tested the updated rounded-cylinder implementation on current main at commit c6acd4e5a199f56052ba74b8e9d735a2157ba613.
The geometry side now looks good: radius=70 mm, height=30 mm, sradius=5 mm gives the expected 140 mm × 30 mm outer wheel envelope, and both utest_COLL_rounded_shapes and the nearby Bullet utility tests pass.
Before going further with the full robot, I reduced the issue to a very small standalone NSC/Bullet reproducer: one rigid wheel, one flat box, and a minimal support constraint. I also included a standard-cylinder control.
What I see appears not to be RoundedCylinder-specific.
With zero envelope and zero safe margin, both RoundedCylinder and Cylinder show highly intermittent support. With zero envelope and a common 0.1 mm safe margin:
The forces are balanced by the support constraint and the full force-balance residual is below 1e-7 N, so the arithmetic is internally consistent.
For RoundedCylinder with friction set to zero, the mean lateral force drops to about +0.50 N, but support is still intermittent.
I therefore do not think this is evidence of a RoundedCylinder-specific bug. It may instead be that my NSC/Bullet margin/envelope settings or the support fixture are not the right baseline for this kind of small rigid wheel.
I attached a minimal standalone reproducer containing only:
Could you please advise what collision envelope, safe margin, and NSC solver settings you would recommend as a baseline for a rigid wheel of about 70 mm radius on rigid flat terrain? I would also appreciate any comments on whether the minimal support fixture in the reproducer is appropriate for this test.
Best regards,
Kirill