Skip to content

Commit 46838eb

Browse files
authored
Fix: Validate SphereShape radius to prevent assertion failures (DART 7) (#2442)
1 parent 74a67fc commit 46838eb

File tree

5 files changed

+87
-2
lines changed

5 files changed

+87
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
- Added validation for invalid contact surface parameters (NaN/Inf/negative friction, restitution, and slip compliance) to prevent LCP solver crashes. ([gazebosim/gz-physics#841](https://github.com/gazebosim/gz-physics/issues/841))
6363

6464
- Collision and Geometry
65+
- Validate `SphereShape::setRadius()` to reject NaN, infinity, and non-positive values with a warning instead of crashing via assertion. ([#2442](https://github.com/dartsim/dart/pull/2442), [gz-physics#843](https://github.com/gazebosim/gz-physics/issues/843))
6566
- Mesh and shape pipeline upgrades: convex mesh collisions/rendering, polygon mesh support, TriMesh internal representation, Collada unit scaling, aiScene ownership fixes, deep-copy shape cloning, ArrowShape material ownership, heightmap fixes, and allocator/heightmap cleanup. ([#2338](https://github.com/dartsim/dart/pull/2338), [#2340](https://github.com/dartsim/dart/pull/2340), [#2325](https://github.com/dartsim/dart/pull/2325), [#2152](https://github.com/dartsim/dart/pull/2152), [#2285](https://github.com/dartsim/dart/pull/2285), [#2239](https://github.com/dartsim/dart/pull/2239), [#2290](https://github.com/dartsim/dart/pull/2290), [#2305](https://github.com/dartsim/dart/pull/2305), [#2287](https://github.com/dartsim/dart/pull/2287), [#2286](https://github.com/dartsim/dart/pull/2286), [#2069](https://github.com/dartsim/dart/pull/2069), [#453](https://github.com/dartsim/dart/issues/453), [#872](https://github.com/dartsim/dart/issues/872), [#896](https://github.com/dartsim/dart/issues/896), [#287](https://github.com/dartsim/dart/issues/287))
6667
- Collision backend fixes across FCL/Bullet/ODE: contact normalization, mesh regressions, contact ordering, plane handling, phantom contact filtering, ellipsoid rolling, sphere containment, and capsule contact stabilization. ([#2339](https://github.com/dartsim/dart/pull/2339), [#2258](https://github.com/dartsim/dart/pull/2258), [#2282](https://github.com/dartsim/dart/pull/2282), [#2243](https://github.com/dartsim/dart/pull/2243), [#2276](https://github.com/dartsim/dart/pull/2276), [#2246](https://github.com/dartsim/dart/pull/2246), [#2274](https://github.com/dartsim/dart/pull/2274), [#2271](https://github.com/dartsim/dart/pull/2271), [#2219](https://github.com/dartsim/dart/pull/2219), [#2125](https://github.com/dartsim/dart/pull/2125), [#1539](https://github.com/dartsim/dart/issues/1539), [#1184](https://github.com/dartsim/dart/issues/1184))
6768
- Collision utilities and filtering updates: raycast filters, collision shape signals, collision filter guards, MetaSkeleton subscription handling, contact helpers, and optional backend embedding. ([#2279](https://github.com/dartsim/dart/pull/2279), [#2250](https://github.com/dartsim/dart/pull/2250), [#2343](https://github.com/dartsim/dart/pull/2343), [#2277](https://github.com/dartsim/dart/pull/2277), [#2245](https://github.com/dartsim/dart/pull/2245), [#2194](https://github.com/dartsim/dart/pull/2194))

dart/dynamics/SphereShape.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@
3232

3333
#include "dart/dynamics/SphereShape.hpp"
3434

35+
#include "dart/common/Logging.hpp"
3536
#include "dart/common/Macros.hpp"
3637
#include "dart/math/Helpers.hpp"
3738

39+
#include <cmath>
40+
3841
namespace dart {
3942
namespace dynamics {
4043

@@ -66,7 +69,13 @@ std::string_view SphereShape::getStaticType()
6669
//==============================================================================
6770
void SphereShape::setRadius(double radius)
6871
{
69-
DART_ASSERT(radius > 0.0);
72+
if (!std::isfinite(radius) || radius <= 0.0) {
73+
DART_WARN(
74+
"SphereShape::setRadius: Invalid radius '{}'. "
75+
"Radius must be a positive finite value. Ignoring request.",
76+
radius);
77+
return;
78+
}
7079

7180
mRadius = radius;
7281

dart/dynamics/SphereShape.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class DART_API SphereShape : public Shape
8080

8181
private:
8282
/// Radius of this Sphere
83-
double mRadius;
83+
double mRadius{1.0};
8484
};
8585

8686
} // namespace dynamics

tests/unit/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ dart_add_test("unit" UNIT_dynamics_ScrewJoint dynamics/test_ScrewJoint.cpp)
8585
dart_add_test("unit" UNIT_dynamics_ShapeNodePtr dynamics/test_ShapeNodePtr.cpp)
8686
dart_add_test("unit" UNIT_dynamics_MeshShape dynamics/test_MeshShape.cpp)
8787
dart_add_test("unit" UNIT_dynamics_HeightmapShape dynamics/test_HeightmapShape.cpp)
88+
dart_add_test("unit" UNIT_dynamics_SphereShape dynamics/test_SphereShape.cpp)
8889
dart_add_test("unit" UNIT_dynamics_ConvexMeshShape dynamics/test_ConvexMeshShape.cpp)
8990
dart_add_test("unit" UNIT_dynamics_BodyNodeDerivatives dynamics/test_BodyNodeDerivatives.cpp)
9091
dart_add_test(
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) 2011-2025, The DART development contributors
2+
3+
#include <dart/dynamics/SphereShape.hpp>
4+
5+
#include <gtest/gtest.h>
6+
7+
#include <limits>
8+
9+
#include <cmath>
10+
11+
//==============================================================================
12+
TEST(SphereShapeTest, ValidRadiusAccepted)
13+
{
14+
auto sphere = std::make_shared<dart::dynamics::SphereShape>(1.0);
15+
EXPECT_DOUBLE_EQ(sphere->getRadius(), 1.0);
16+
17+
sphere->setRadius(2.5);
18+
EXPECT_DOUBLE_EQ(sphere->getRadius(), 2.5);
19+
20+
sphere->setRadius(0.001);
21+
EXPECT_DOUBLE_EQ(sphere->getRadius(), 0.001);
22+
}
23+
24+
//==============================================================================
25+
TEST(SphereShapeTest, NaNRadiusRejected)
26+
{
27+
auto sphere = std::make_shared<dart::dynamics::SphereShape>(1.0);
28+
const double originalRadius = sphere->getRadius();
29+
30+
sphere->setRadius(std::nan(""));
31+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
32+
33+
sphere->setRadius(std::numeric_limits<double>::quiet_NaN());
34+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
35+
36+
sphere->setRadius(std::numeric_limits<double>::signaling_NaN());
37+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
38+
}
39+
40+
//==============================================================================
41+
TEST(SphereShapeTest, InfiniteRadiusRejected)
42+
{
43+
auto sphere = std::make_shared<dart::dynamics::SphereShape>(1.0);
44+
const double originalRadius = sphere->getRadius();
45+
46+
sphere->setRadius(std::numeric_limits<double>::infinity());
47+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
48+
49+
sphere->setRadius(-std::numeric_limits<double>::infinity());
50+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
51+
}
52+
53+
//==============================================================================
54+
TEST(SphereShapeTest, NonPositiveRadiusRejected)
55+
{
56+
auto sphere = std::make_shared<dart::dynamics::SphereShape>(1.0);
57+
const double originalRadius = sphere->getRadius();
58+
59+
sphere->setRadius(0.0);
60+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
61+
62+
sphere->setRadius(-1.0);
63+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
64+
65+
sphere->setRadius(-0.001);
66+
EXPECT_DOUBLE_EQ(sphere->getRadius(), originalRadius);
67+
}
68+
69+
//==============================================================================
70+
TEST(SphereShapeTest, ConstructorWithSmallValidRadius)
71+
{
72+
auto sphere = std::make_shared<dart::dynamics::SphereShape>(1e-10);
73+
EXPECT_GT(sphere->getRadius(), 0.0);
74+
}

0 commit comments

Comments
 (0)