Skip to content

Commit 5059bb8

Browse files
ahcordeAshton Larkin
and
Ashton Larkin
authored
sdf -> usd Parse links and ground planes (#828)
Signed-off-by: ahcorde <ahcorde@gmail.com> Signed-off-by: Ashton Larkin <ashton@osrfoundation.org> Co-authored-by: Ashton Larkin <ashton@osrfoundation.org>
1 parent ae3655f commit 5059bb8

12 files changed

+810
-15
lines changed

usd/include/sdf/usd/sdf_parser/Light.hh

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace sdf
4747
/// of _light.
4848
/// \param[in] _path The USD path of the parsed light in _stage, which must
4949
/// be a valid USD path.
50-
/// \return UsdErrors, which is a vector of Error objects. Each Error
50+
/// \return UsdErrors, which is a vector of UsdError objects. Each UsdError
5151
/// includes an error code and message. An empty vector indicates no error.
5252
UsdErrors IGNITION_SDFORMAT_USD_VISIBLE ParseSdfLight(
5353
const sdf::Light &_light,
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (C) 2022 Open Source Robotics Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#ifndef SDF_USD_SDF_PARSER_LINK_HH_
19+
#define SDF_USD_SDF_PARSER_LINK_HH_
20+
21+
#include <string>
22+
23+
// TODO(ahcorde):this is to remove deprecated "warnings" in usd, these warnings
24+
// are reported using #pragma message so normal diagnostic flags cannot remove
25+
// them. This workaround requires this block to be used whenever usd is
26+
// included.
27+
#pragma push_macro ("__DEPRECATED")
28+
#undef __DEPRECATED
29+
#include <pxr/usd/usd/stage.h>
30+
#pragma pop_macro ("__DEPRECATED")
31+
32+
#include "sdf/Link.hh"
33+
#include "sdf/usd/Export.hh"
34+
#include "sdf/usd/UsdError.hh"
35+
#include "sdf/sdf_config.h"
36+
37+
namespace sdf
38+
{
39+
// Inline bracke to help doxygen filtering.
40+
inline namespace SDF_VERSION_NAMESPACE {
41+
//
42+
namespace usd
43+
{
44+
/// \brief Parse an SDF link into a USD stage.
45+
/// \param[in] _link The SDF link to parse.
46+
/// \param[in] _stage The stage that should contain the USD representation
47+
/// of _link. This must be a valid, initialized stage.
48+
/// \param[in] _path The USD path of the parsed link in _stage, which must
49+
/// be a valid USD path.
50+
/// \param[in] _rigidBody Whether the link is a rigid body (i.e.,
51+
/// non-static) or not. True for rigid body, false otherwise
52+
/// \return UsdErrors, which is a vector of UsdError objects. Each UsdError
53+
/// includes an error code and message. An empty vector indicates no errors
54+
/// occurred when parsing _link to its USD representation.
55+
UsdErrors IGNITION_SDFORMAT_USD_VISIBLE ParseSdfLink(const sdf::Link &_link,
56+
pxr::UsdStageRefPtr &_stage, const std::string &_path,
57+
bool _rigidBody);
58+
}
59+
}
60+
}
61+
62+
#endif
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (C) 2022 Open Source Robotics Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#ifndef SDF_USD_SDF_PARSER_MODEL_HH_
19+
#define SDF_USD_SDF_PARSER_MODEL_HH_
20+
21+
#include <string>
22+
23+
// TODO(ahcorde) this is to remove deprecated "warnings" in usd, these warnings
24+
// are reported using #pragma message so normal diagnostic flags cannot remove
25+
// them. This workaround requires this block to be used whenever usd is
26+
// included.
27+
#pragma push_macro ("__DEPRECATED")
28+
#undef __DEPRECATED
29+
#include <pxr/usd/sdf/path.h>
30+
#include <pxr/usd/usd/stage.h>
31+
#pragma pop_macro ("__DEPRECATED")
32+
33+
#include "sdf/Model.hh"
34+
#include "sdf/usd/Export.hh"
35+
#include "sdf/usd/UsdError.hh"
36+
#include "sdf/sdf_config.h"
37+
38+
namespace sdf
39+
{
40+
// Inline bracke to help doxygen filtering.
41+
inline namespace SDF_VERSION_NAMESPACE {
42+
//
43+
namespace usd
44+
{
45+
/// \brief Parse an SDF model into a USD stage.
46+
/// \param[in] _model The SDF model to parse.
47+
/// \param[in] _stage The stage that should contain the USD representation
48+
/// of _model. This must be a valid, initialized stage.
49+
/// \param[in] _path The USD path of the parsed model in _stage, which must
50+
/// be a valid USD path.
51+
/// \param[in] _worldPath The path to the USD world prim. This is needed if
52+
/// the model has any joints with the world as its parent.
53+
/// \return UsdErrors, which is a vector of UsdError objects. Each UsdError
54+
/// includes an error code and message. An empty vector indicates no error
55+
/// occurred when parsing _model to its USD representation.
56+
UsdErrors IGNITION_SDFORMAT_USD_VISIBLE ParseSdfModel(
57+
const sdf::Model &_model, pxr::UsdStageRefPtr &_stage,
58+
const std::string &_path, const pxr::SdfPath &_worldPath);
59+
}
60+
}
61+
}
62+
63+
#endif

usd/src/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
set(sources
22
UsdError.cc
33
sdf_parser/Light.cc
4+
sdf_parser/Link.cc
5+
sdf_parser/Model.cc
46
sdf_parser/World.cc
57
)
68

@@ -20,6 +22,9 @@ target_link_libraries(${usd_target}
2022
set(gtest_sources
2123
sdf_parser/sdf2usd_TEST.cc
2224
sdf_parser/Light_Sdf2Usd_TEST.cc
25+
sdf_parser/Link_Sdf2Usd_TEST.cc
26+
# TODO(adlarkin) add a test for SDF -> USD models once model parsing
27+
# functionality is complete
2328
sdf_parser/World_Sdf2Usd_TEST.cc
2429
UsdError_TEST.cc
2530
UsdUtils_TEST.cc

usd/src/UsdTestUtils.hh

+81
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,22 @@
2020
#include <gtest/gtest.h>
2121
#include <ignition/math/Angle.hh>
2222
#include <ignition/math/Pose3.hh>
23+
24+
// TODO(ahcorde):this is to remove deprecated "warnings" in usd, these warnings
25+
// are reported using #pragma message so normal diagnostic flags cannot remove
26+
// them. This workaround requires this block to be used whenever usd is
27+
// included.
28+
#pragma push_macro ("__DEPRECATED")
29+
#undef __DEPRECATED
30+
#include <pxr/base/gf/quatf.h>
2331
#include <pxr/base/gf/vec3d.h>
2432
#include <pxr/base/gf/vec3f.h>
2533
#include <pxr/base/tf/token.h>
2634
#include <pxr/usd/usd/attribute.h>
2735
#include <pxr/usd/usd/prim.h>
36+
#include <pxr/usd/usdPhysics/massAPI.h>
37+
#include <pxr/usd/usdPhysics/rigidBodyAPI.h>
38+
#pragma pop_macro ("__DEPRECATED")
2839

2940
#include "sdf/system_util.hh"
3041

@@ -95,6 +106,76 @@ void CheckPrimPose(const pxr::UsdPrim &_usdPrim,
95106
EXPECT_TRUE(checkedOpOrder);
96107
}
97108

109+
/// \brief Compare the Inertial of a USD prim to the desired values
110+
/// \param[in] _usdPrim The USD prim
111+
/// \param[in] _targetMass Mass of the link that _usdPrim should have
112+
/// \param[in] _targetDiagonalInertia Diagonal Inertia that _usdPrim should have
113+
/// \param[in] _targetPrincipalAxes The principal axes that _usdPrim should have
114+
/// \param[in] _targetCenterOfMass Center of mass that _usdPrim should have
115+
/// \param[in] _isRigid True if _usdPrim should be a rigid body, False otherwise
116+
void CheckInertial(const pxr::UsdPrim &_usdPrim,
117+
float _targetMass,
118+
const pxr::GfVec3f &_targetDiagonalInertia,
119+
const pxr::GfQuatf &_targetPrincipalAxes,
120+
const pxr::GfVec3f &_targetCenterOfMass,
121+
bool _isRigid)
122+
{
123+
bool checkedMass = false;
124+
if (auto massAttr =
125+
_usdPrim.GetAttribute(pxr::TfToken("physics:mass")))
126+
{
127+
float massUSD;
128+
massAttr.Get(&massUSD);
129+
EXPECT_FLOAT_EQ(_targetMass, massUSD);
130+
checkedMass = true;
131+
}
132+
EXPECT_TRUE(checkedMass);
133+
134+
bool checkedDiagInertia = false;
135+
if (auto diagInertiaAttr =
136+
_usdPrim.GetAttribute(pxr::TfToken("physics:diagonalInertia")))
137+
{
138+
pxr::GfVec3f diagonalInertiaUSD;
139+
diagInertiaAttr.Get(&diagonalInertiaUSD);
140+
EXPECT_FLOAT_EQ(_targetDiagonalInertia[0], diagonalInertiaUSD[0]);
141+
EXPECT_FLOAT_EQ(_targetDiagonalInertia[1], diagonalInertiaUSD[1]);
142+
EXPECT_FLOAT_EQ(_targetDiagonalInertia[2], diagonalInertiaUSD[2]);
143+
checkedDiagInertia = true;
144+
}
145+
EXPECT_TRUE(checkedDiagInertia);
146+
147+
bool checkedPrincipalAxes = false;
148+
if (auto principalAxesAttr =
149+
_usdPrim.GetAttribute(pxr::TfToken("physics:principalAxes")))
150+
{
151+
pxr::GfQuatf principalAxesUSD;
152+
principalAxesAttr.Get(&principalAxesUSD);
153+
EXPECT_FLOAT_EQ(principalAxesUSD.GetReal(), _targetPrincipalAxes.GetReal());
154+
const auto &usdImaginary = principalAxesUSD.GetImaginary();
155+
const auto &targetImaginary = _targetPrincipalAxes.GetImaginary();
156+
EXPECT_FLOAT_EQ(usdImaginary[0], targetImaginary[0]);
157+
EXPECT_FLOAT_EQ(usdImaginary[1], targetImaginary[1]);
158+
EXPECT_FLOAT_EQ(usdImaginary[2], targetImaginary[2]);
159+
checkedPrincipalAxes = true;
160+
}
161+
EXPECT_TRUE(checkedPrincipalAxes);
162+
163+
bool checkedCOM = false;
164+
if (auto comAttr =
165+
_usdPrim.GetAttribute(pxr::TfToken("physics:centerOfMass")))
166+
{
167+
pxr::GfVec3f centerOfMassUSD;
168+
comAttr.Get(&centerOfMassUSD);
169+
EXPECT_FLOAT_EQ(_targetCenterOfMass[0], centerOfMassUSD[0]);
170+
EXPECT_FLOAT_EQ(_targetCenterOfMass[1], centerOfMassUSD[1]);
171+
EXPECT_FLOAT_EQ(_targetCenterOfMass[2], centerOfMassUSD[2]);
172+
checkedCOM = true;
173+
}
174+
EXPECT_TRUE(checkedCOM);
175+
176+
EXPECT_EQ(_isRigid, _usdPrim.HasAPI<pxr::UsdPhysicsRigidBodyAPI>());
177+
EXPECT_EQ(_isRigid, _usdPrim.HasAPI<pxr::UsdPhysicsMassAPI>());
178+
}
98179
} // namespace testing
99180
} // namespace usd
100181
}

usd/src/UsdUtils.hh

+31-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <ignition/math/Vector3.hh>
2424
#include <ignition/math/Quaternion.hh>
2525

26-
// TODO(adlarkin):this is to remove deprecated "warnings" in usd, these warnings
26+
// TODO(adlarkin) this is to remove deprecated "warnings" in usd, these warnings
2727
// are reported using #pragma message so normal diagnostic flags cannot remove
2828
// them. This workaround requires this block to be used whenever usd is
2929
// included.
@@ -34,8 +34,13 @@
3434
#include <pxr/usd/usdGeom/xformCommonAPI.h>
3535
#pragma pop_macro ("__DEPRECATED")
3636

37+
#include "sdf/Collision.hh"
3738
#include "sdf/Error.hh"
39+
#include "sdf/Geometry.hh"
40+
#include "sdf/Link.hh"
41+
#include "sdf/Model.hh"
3842
#include "sdf/SemanticPose.hh"
43+
#include "sdf/Visual.hh"
3944
#include "sdf/system_util.hh"
4045
#include "sdf/usd/Export.hh"
4146
#include "sdf/usd/UsdError.hh"
@@ -118,6 +123,31 @@ namespace sdf
118123

119124
return errors;
120125
}
126+
127+
/// \brief Check if an sdf model is static and contains a single link that
128+
/// contains a single visual and single collision that both have a plane
129+
/// geometry.
130+
/// \param[in] _model The sdf model to check
131+
/// \return True if _model is static and has only one link with one visual
132+
/// and one collision that have a plane geometry. False otherwise
133+
/// \note This method will no longer be needed when a pxr::USDGeomPlane
134+
/// class is created
135+
inline bool SDFORMAT_VISIBLE IsPlane(const sdf::Model &_model)
136+
{
137+
if (!_model.Static() || _model.LinkCount() != 1u)
138+
return false;
139+
140+
const auto &link = _model.LinkByIndex(0u);
141+
if ((link->VisualCount() != 1u) || (link->CollisionCount() != 1u))
142+
return false;
143+
144+
const auto &visual = link->VisualByIndex(0u);
145+
if (visual->Geom()->Type() != sdf::GeometryType::PLANE)
146+
return false;
147+
148+
const auto &collision = link->CollisionByIndex(0u);
149+
return collision->Geom()->Type() == sdf::GeometryType::PLANE;
150+
}
121151
}
122152
}
123153
}

usd/src/UsdUtils_TEST.cc

+25
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030
#include <pxr/usd/usdGeom/xform.h>
3131
#pragma pop_macro ("__DEPRECATED")
3232

33+
#include "sdf/Light.hh"
3334
#include "sdf/Link.hh"
3435
#include "sdf/Model.hh"
3536
#include "sdf/Root.hh"
37+
#include "sdf/World.hh"
3638
#include "test_config.h"
3739
#include "test_utils.hh"
3840
#include "UsdTestUtils.hh"
@@ -87,3 +89,26 @@ TEST(UsdUtils, SetPose)
8789

8890
sdf::usd::testing::CheckPrimPose(prim, pose);
8991
}
92+
93+
//////////////////////////////////////////////////
94+
TEST(UsdUtils, IsPlane)
95+
{
96+
const auto path = sdf::testing::TestFile("sdf", "empty.sdf");
97+
sdf::Root root;
98+
99+
ASSERT_TRUE(sdf::testing::LoadSdfFile(path, root));
100+
ASSERT_EQ(1u, root.WorldCount());
101+
const auto world = root.WorldByIndex(0u);
102+
ASSERT_NE(nullptr, world);
103+
104+
ASSERT_EQ(1u, world->ModelCount());
105+
const auto model = world->ModelByIndex(0u);
106+
ASSERT_NE(nullptr, model);
107+
EXPECT_TRUE(sdf::usd::IsPlane(*model));
108+
109+
// make the model non-static to verify it's no longer considered a plane
110+
auto mutableModel = const_cast<sdf::Model *>(model);
111+
ASSERT_NE(nullptr, mutableModel);
112+
mutableModel->SetStatic(false);
113+
EXPECT_FALSE(sdf::usd::IsPlane(*mutableModel));
114+
}

0 commit comments

Comments
 (0)