AGX Dynamics 2.42.3.1
Loading...
Searching...
No Matches
TrackUtils.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#pragma once
18
19#include <agxVehicle/Track.h>
20
21#include <agxCollide/Box.h>
22
23#include <agxRender/Color.h>
24
26{
31 inline void createGeometryBox( const TrackNode& node )
32 {
35 geometry->setLocalTransform( transform );
36 node.getRigidBody()->add( geometry );
37 }
38
45 template<typename ContainerT>
46 IndexRangeContainer splitNonconsecutive( const ContainerT& container )
47 {
48 if ( container.size() < 2 )
49 return IndexRangeContainer{ IndexRange( 0, container.size() ) };
50
51 agxAssert( std::is_sorted( container.begin(), container.end() ) );
52
53 IndexRangeContainer result{ IndexRange( 0, 1 ) };
54 for ( agx::UInt i = 1; i < container.size(); ++i ) {
55 if ( container[ i ] == container[ i - 1 ] + typename ContainerT::value_type( 1 ) )
56 ++result.back().end();
57 else
58 result.push_back( agx::IndexRange( i, i + 1 ) );
59 }
60
61 return result;
62 }
63
73 template<typename ContainerT>
74 IndexRangeContainer splitNonconsecutive( const Track& track, const ContainerT& container )
75 {
76 auto result = splitNonconsecutive( container );
77
78 agxAssert( !result.empty() );
79 if ( result.size() == 1 && result.front().empty() )
80 return IndexRangeContainer{};
81
82 // Transform ranges from indices to container values. E.g.,
83 // 2 4 7 [9 10 11 12] 18
84 // index: 3 ... 6
85 // range original: begin = 3, end = 7
86 // range transformed: begin = 9, end = 13
87 for ( agx::UInt i = 0; i < result.size(); ++i ) {
88 auto& range = result[ i ];
89 const auto size = range.size();
90 range.begin() = container[ range.begin() ];
91 range.end() = range.begin() + size;
92 }
93
94 if ( result.size() < 2 )
95 return result;
96
97 // Including the last range in the first if the first node belongs
98 // to the first range and the last node to the last.
99 const auto numNodes = track.nodes().size();
100 if ( result.front().begin() == agx::UInt( 0 ) && result.back().end() == numNodes ) {
101 result.front().begin() = result.back().begin();
102 result.pop_back();
103 }
104
105 return result;
106 }
107
111 template<typename T>
112 inline T prevIndex( T index, T size )
113 {
114 agxAssert( size > 0 && index != agx::InvalidIndex );
115 return index == 0 ? size - 1 : index - 1;
116 }
117
121 template<typename T>
122 inline T nextIndex( T index, T size )
123 {
124 agxAssert( size > 0 && index != agx::InvalidIndex );
125 return ( index + 1 ) % size;
126 }
127
134 inline TrackNodeRange createRangeExcludingNodeIndex( const Track& track, agx::UInt nodeIndex, agx::Int signedNumNodes )
135 {
136 const auto totalNumNodes = track.nodes().size();
137 if ( totalNumNodes < 1 )
138 return track.nodes();
139
140 const agx::UInt numNodes = signedNumNodes < 0 ?
141 (agx::UInt)-signedNumNodes :
142 (agx::UInt)signedNumNodes;
143 agx::UInt beginIndex = agx::InvalidIndex;
144 agx::UInt endIndex = agx::InvalidIndex;
145 if ( signedNumNodes < 0 ) {
146 beginIndex = nodeIndex > numNodes ?
147 nodeIndex - numNodes :
148 nodeIndex + totalNumNodes - numNodes;
149 endIndex = nodeIndex;
150 }
151 else {
152 beginIndex = ( nodeIndex + 1 ) % totalNumNodes;
153 endIndex = ( nodeIndex + numNodes + 1 ) % totalNumNodes;
154 }
155
156 return TrackNodeRange( track.getIterator( beginIndex ), track.getIterator( endIndex ) );
157 }
158
171 const agx::Vec3& direction,
172 const agx::Vec3& wheelPlaneNormal )
173 {
174 auto q = agx::Quat();
175 q *= agx::Quat::rotate( q * agx::Vec3::Z_AXIS(), direction );
176 q *= agx::Quat::rotate( q * agx::Vec3::Y_AXIS(), wheelPlaneNormal );
177 q *= agx::Quat::rotate( q * agx::Vec3::X_AXIS(), ( wheelPlaneNormal ^ direction ).normal() );
178
179 return agx::AffineMatrix4x4{ q, position };
180 }
181
187 {
188 const auto trackThickness = track.getRoute()->getNodeThickness();
189 const auto trackNodeLength = track.getRoute()->getNodeLength();
190
191 return trackThickness + 0.25 * trackNodeLength;
192 }
193
200
209 AGXVEHICLE_EXPORT bool isTrackSegment( const Track& track, const agx::RigidBody& rb );
210
217 AGXVEHICLE_EXPORT const TrackWheel* findWheel( const Track& track, const agx::RigidBody& rb );
218
223 const agxRender::Color& tangentColor = agxRender::Color::OrangeRed(),
225 agx::Real scale = 1.0 );
226
227
236
250
252 {
256 bool isOverlapping() const;
257
261 operator bool() const;
262
263 const TrackWheel* wheel = nullptr;
264 };
265
270 {
280 static WheelSegmentOverlap test( const TrackWheel& wheel,
281 const agx::Vec3& sBegin,
282 const agx::Vec3& sEnd,
283 agx::Real additionalRadius = 0.0 );
284
293 static WheelSegmentOverlap test( const TrackWheel& wheel,
294 const WheelTangentData& tangent,
295 agx::Real additionalRadius = 0.0 );
296
300 void render() const;
301
304 };
305
310 {
319 static WheelPointOverlap test( const TrackWheel& wheel,
320 const agx::Vec3& point,
321 agx::Real additionalRadius = 0.0 );
322
323 agx::Real depth = 0.0;
324 agx::Vec3 normal{};
325 };
326
333 {
335 {
336 BELOW = -1, // Inside the segment and on the wheel-facing side.
337 OUTSIDE = 0, // Not within the begin - end interval.
338 ABOVE = 1 // Inside the segment and on the outer side.
339 };
340
346 static bool inside( const agx::Vec3& point, const WheelTangentData& tangent );
347
353 static Location findLocation( const agx::Vec3& point, const WheelTangentData& tangent );
354 };
355
368 {
369 public:
370 struct iterator
371 {
372 iterator( size_t index1,
373 size_t index2,
374 size_t size,
375 size_t numLoops = 0 )
376 : m_index1( index1 )
377 , m_index2( index2 )
378 , m_numLoops( 2 * numLoops )
379 , m_size( size )
380 {
381 }
382
383 iterator( const iterator& ) = delete;
384 iterator& operator=( const iterator& ) = delete;
385
387 {
388 m_index1 = nextIndex( m_index1 );
389 m_index2 = nextIndex( m_index2 );
390 return *this;
391 }
392
393 std::pair<size_t, size_t> operator*() const
394 {
395 return { m_index1, m_index2 };
396 }
397
398 bool operator==( const iterator& other ) const
399 {
400 return this->m_index1 == other.m_index1 &&
401 this->m_index2 == other.m_index2 &&
402 this->m_numLoops == other.m_numLoops;
403 }
404
405 bool operator!=( const iterator& other ) const
406 {
407 return !( ( *this ) == other );
408 }
409
410 private:
411 inline size_t nextIndex( size_t index )
412 {
413 m_numLoops += ( index + 1 ) == m_size;
414 return ( index + 1 ) % m_size;
415 }
416
417 private:
418 size_t m_index1;
419 size_t m_index2;
420 size_t m_numLoops;
421 size_t m_size;
422 };
423
424 public:
426 : m_size( size )
427 {
428 }
429
431 {
432 return { 0, 1, m_size };
433 }
434
435 iterator end() const
436 {
437 return { 0, 1, m_size, 1 };
438 }
439
440 private:
441 size_t m_size = 0;
442 };
443
457 template<typename ContainerT>
459 {
460 public:
461 struct iterator
462 {
463 using reference = typename ContainerT::reference;
464 using pair = std::pair<reference, reference>;
465
466 iterator( size_t index1,
467 size_t index2,
468 ContainerT& container,
469 size_t numLoops = 0 )
470 : m_it( index1, index2, container.size(), numLoops )
471 , m_container( container )
472 {
473 }
474
475 iterator( const iterator& ) = delete;
476 iterator& operator=( const iterator& ) = delete;
477
479 {
480 ++m_it;
481 return *this;
482 }
483
485 {
486 const auto [index1, index2] = *m_it;
487 return { (reference)m_container[ index1 ], (reference)m_container[ index2 ] };
488 }
489
490 bool operator==( const iterator& other ) const
491 {
492 return this->m_it == other.m_it;
493 }
494
495 bool operator!=( const iterator& other ) const
496 {
497 return !( ( *this ) == other );
498 }
499
500 private:
502 ContainerT& m_container;
503 };
504
505 public:
506 OneOffCircularView( ContainerT& container )
507 : m_container( container )
508 {
509 }
510
512 {
513 return { 0, 1, m_container };
514 }
515
517 {
518 return { 0, 1, m_container, 1 };
519 }
520
521 private:
522 ContainerT& m_container;
523 };
524
525 template<typename T>
526 auto circularView( const T& foo )
527 {
528 if constexpr ( std::is_integral_v<T> )
529 return OneOffCircularIndexView{ (size_t)foo };
530 else
531 return OneOffCircularView{ foo };
532 }
533}
#define AGXVEHICLE_EXPORT
A box shape for geometric intersection tests.
Definition: Box.h:33
The geometry representation used by the collision detection engine.
Definition: Geometry.h:92
Utility color class with "common colors".
Definition: Color.h:48
static agxRender::Color OrangeRed()
Definition: Color.h:178
static agxRender::Color GreenYellow()
Definition: Color.h:246
Segment range object for linked structure.
const agx::Vec3 & getHalfExtents() const
agx::RigidBody * getRigidBody() const
Node/segment/shoe object in agxVehicle::Track.
Definition: TrackNode.h:47
Object containing properties of an agxVehicle::Track.
agx::Real getNodeLength() const
agx::Real getNodeThickness() const
Wheel used in tracked vehicles.
Definition: TrackWheel.h:32
Assembly object representing a continuous track with a given number of shoes (nodes).
NodeRange nodes() const
Iterator getIterator(agx::UInt index) const
TrackRoute * getRoute() const
View of indices given size, e.g., for ( auto [curr, next] : OneOffCircularIndexView{ 5 } ) ....
Definition: TrackUtils.h:368
View a container with current value and next at the same time.
Definition: TrackUtils.h:459
OneOffCircularView(ContainerT &container)
Definition: TrackUtils.h:506
static AffineMatrix4x4T< Real > translate(const Vec3T< Real > &dv)
Return a matrix which translates according to dv.
size_t size() const
Definition: Container.h:134
static QuatT< Real > rotate(Real angle, Real x, Real y, Real z)
Static method which constructs and returns a Quaternion from a rotation given as angle radians around...
Definition: QuatTemplate.h:743
The rigid body class, combining a geometric model and a frame of reference.
Definition: RigidBody.h:49
bool add(agxCollide::Geometry *geometry, const agx::AffineMatrix4x4 &localTransform, bool incrementalMassCalculation=false)
Connect a geometry to this rigid body.
static Vec3T Y_AXIS()
Definition: Vec3Template.h:777
static Vec3T Z_AXIS()
Definition: Vec3Template.h:783
static Vec3T X_AXIS()
Definition: Vec3Template.h:771
#define agxAssert(expr)
Definition: debug.h:143
AGXVEHICLE_EXPORT void setTrackStiffnessFromCompliance(TrackProperties *properties, agx::Real compliance, agx::Real nodeLength)
Set track stiffness from the deprecated compliance parameter that previously where defined per hinge ...
T nextIndex(T index, T size)
Definition: TrackUtils.h:122
AGXVEHICLE_EXPORT bool isTrackSegment(const Track &track, const agx::RigidBody &rb)
Check if the given rb is a track segment type of body, e.g., a node or a segment sensor.
agx::Real getNodeWheelOverlapThreshold(const Track &track)
Definition: TrackUtils.h:186
AGXVEHICLE_EXPORT Track::TrackWheelContainer getWheelsAlongTrack(const Track &track)
Finds the wheels (sorted) along the given track with the reference wheel as the first instance.
TrackNodeRange createRangeExcludingNodeIndex(const Track &track, agx::UInt nodeIndex, agx::Int signedNumNodes)
Creates a node range where nodeIndex is excluded and number of nodes to include is signed.
Definition: TrackUtils.h:134
AGXVEHICLE_EXPORT const TrackWheel * findWheel(const Track &track, const agx::RigidBody &rb)
Finds the wheel instance in the given track if rb is a track sensor of the wheel.
IndexRangeContainer splitNonconsecutive(const ContainerT &container)
Given a sorted container this function will split the content into ranges where the elements are cons...
Definition: TrackUtils.h:46
auto circularView(const T &foo)
Definition: TrackUtils.h:526
void createGeometryBox(const TrackNode &node)
Default node geometry generator.
Definition: TrackUtils.h:31
agx::AffineMatrix4x4 calculateNodeTransform(const agx::Vec3 &position, const agx::Vec3 &direction, const agx::Vec3 &wheelPlaneNormal)
Calculates the transform of a track node given position, direction (along the track) and wheel plane ...
Definition: TrackUtils.h:170
AGXVEHICLE_EXPORT void debugRender(const WheelTangentData &tangent, const agxRender::Color &tangentColor=agxRender::Color::OrangeRed(), const agxRender::Color &upColor=agxRender::Color::GreenYellow(), agx::Real scale=1.0)
Debug render wheel tangent, including up vector.
T prevIndex(T index, T size)
Definition: TrackUtils.h:112
agx::IndexRangeT< agx::UInt > IndexRange
Definition: TrackNode.h:35
agxSDK::LinkedSegmentRange< TrackNode > TrackNodeRange
Node range object for tracks.
uint64_t UInt
Definition: Integer.h:27
double Real
Definition: Real.h:41
AGXCORE_EXPORT const InvalidIndexStruct InvalidIndex
QuatT< Real > Quat
Definition: Quat.h:24
int64_t Int
Definition: Integer.h:28
Data for an external tangent between two wheels.
bool operator==(const iterator &other) const
Definition: TrackUtils.h:398
std::pair< size_t, size_t > operator*() const
Definition: TrackUtils.h:393
iterator(size_t index1, size_t index2, size_t size, size_t numLoops=0)
Definition: TrackUtils.h:372
iterator & operator=(const iterator &)=delete
bool operator!=(const iterator &other) const
Definition: TrackUtils.h:405
bool operator==(const iterator &other) const
Definition: TrackUtils.h:490
iterator & operator=(const iterator &)=delete
bool operator!=(const iterator &other) const
Definition: TrackUtils.h:495
std::pair< reference, reference > pair
Definition: TrackUtils.h:464
iterator(size_t index1, size_t index2, ContainerT &container, size_t numLoops=0)
Definition: TrackUtils.h:466
typename ContainerT::reference reference
Definition: TrackUtils.h:463
Tan provides helpers to determine whether a point lies on the segment, defined in the given tangent s...
Definition: TrackUtils.h:333
static bool inside(const agx::Vec3 &point, const WheelTangentData &tangent)
Check whether point lies between tangent.begin and tangent.end.
static Location findLocation(const agx::Vec3 &point, const WheelTangentData &tangent)
If the point is inside the begin - end interval, the sign relative to tangent.up decides ABOVE or BEL...
Data of overlap test between a track wheel and a point.
Definition: TrackUtils.h:310
static WheelPointOverlap test(const TrackWheel &wheel, const agx::Vec3 &point, agx::Real additionalRadius=0.0)
Perform overlap test between wheel and point.
Data of overlap test between a track wheel and a line segment.
Definition: TrackUtils.h:270
static WheelSegmentOverlap test(const TrackWheel &wheel, const agx::Vec3 &sBegin, const agx::Vec3 &sEnd, agx::Real additionalRadius=0.0)
Test overlap of segment sBegin to sEnd vs wheel.
void render() const
Debug render overlap if overlapping, otherwise noting is rendered.
static WheelSegmentOverlap test(const TrackWheel &wheel, const WheelTangentData &tangent, agx::Real additionalRadius=0.0)
Test overlap of tangent vs wheel.