@@ -17,40 +17,51 @@ public class SmartQuadrupedController : IDisposable
17
17
private const float LegHeight = - 9f ;
18
18
private const int LegDistanceLongitudinal = 15 ;
19
19
private const int LegDistanceLateral = 15 ;
20
+ private const int TelemetricsUpdateInterval = 2000 ;
20
21
21
- public LegPositions OriginalRelaxedStance => new LegPositions
22
+ public event EventHandler < QuadrupedTelemetrics > NewTelemetricsUpdate ;
23
+
24
+ public static LegPositions OriginalRelaxedStance => new LegPositions
22
25
(
23
26
new Vector3 ( LegDistanceLateral , LegDistanceLongitudinal , LegHeight ) ,
24
27
new Vector3 ( LegDistanceLateral , - LegDistanceLongitudinal , LegHeight ) ,
25
28
new Vector3 ( - LegDistanceLateral , LegDistanceLongitudinal , LegHeight ) ,
26
29
new Vector3 ( - LegDistanceLateral , - LegDistanceLongitudinal , LegHeight )
27
30
) ;
28
31
29
- public LegPositions RelaxedStance { get ; set ; }
32
+ public LegPositions RelaxedStance { get ; set ; } = OriginalRelaxedStance ;
33
+
30
34
public int Speed { get ; set ; } = 60 ;
31
35
public Vector2 Direction { get ; set ; }
36
+ public float Rotation { get ; set ; }
32
37
33
- private LegPositions _lastWrittenPosition ;
34
38
private Vector2 _odometry = Vector2 . Zero ;
35
- private LegFlags _lastUsedCombo = LegFlags . RfLrCross ;
39
+ public Vector2 Odometry => _odometry ;
40
+ private float _rotationalOdometry = 0f ;
41
+ public float RotationalOdometry => _rotationalOdometry ;
42
+ public Angle Heading => new Angle ( _rotationalOdometry ) ;
43
+
44
+ private LegPositions _lastWrittenPosition ;
45
+ private LegFlags _lastUsedCombo = LegFlags . LfRrCross ;
36
46
private bool _keepRunning = true ;
37
47
private bool _moving ;
38
48
39
49
public SmartQuadrupedController ( QuadrupedIkDriver driver )
40
50
{
41
51
_driver = driver ?? throw new ArgumentNullException ( nameof ( driver ) ) ;
42
- RelaxedStance = OriginalRelaxedStance ;
43
52
_driver . Setup ( ) ;
44
53
_lastWrittenPosition = _driver . ReadCurrentLegPositions ( ) ;
45
- Task . Run ( MainControllerLoop ) ;
54
+ Task . Run ( MainControllerLoop ) . ConfigureAwait ( false ) ;
46
55
}
47
56
48
57
private async Task MainControllerLoop ( )
49
58
{
50
59
await ExecuteMove ( RelaxedStance ) ;
60
+ var watch = new Stopwatch ( ) ;
61
+ watch . Start ( ) ;
51
62
while ( _keepRunning )
52
63
{
53
- if ( Direction . IsZero ( ) )
64
+ if ( Direction . IsZero ( ) && Rotation == 0f )
54
65
{
55
66
if ( _moving )
56
67
{
@@ -59,19 +70,35 @@ private async Task MainControllerLoop()
59
70
}
60
71
else
61
72
{
62
- await Task . Delay ( _updateDelay ) ;
73
+ if ( ! _lastWrittenPosition . MoveFinished ( RelaxedStance ) )
74
+ {
75
+ await ShiftToRelaxed ( ) ;
76
+ }
77
+ else
78
+ {
79
+ await Task . Delay ( _updateDelay ) ;
80
+ }
63
81
}
64
82
}
65
83
else
66
84
{
67
- await ExecuteStep ( Direction , GetNextLegCombo ( ) ) ;
85
+ await ExecuteStep ( Direction , Rotation , GetNextLegCombo ( ) ) ;
68
86
_moving = true ;
69
87
}
70
- Console . WriteLine ( _odometry ) ;
88
+ if ( watch . ElapsedMilliseconds > TelemetricsUpdateInterval )
89
+ {
90
+ watch . Restart ( ) ;
91
+ NewTelemetricsUpdate ? . Invoke ( this , _driver . ReadTelemetrics ( ) ) ;
92
+ }
71
93
}
72
94
_driver . DisableMotors ( ) ;
73
95
}
74
96
97
+ private async Task ShiftToRelaxed ( )
98
+ {
99
+ await ExecuteMove ( RelaxedStance ) ;
100
+ }
101
+
75
102
private async Task StepToRelaxed ( LegFlags legsToAlign , float liftHeight = 2 )
76
103
{
77
104
if ( legsToAlign != LegFlags . LfRrCross && legsToAlign != LegFlags . RfLrCross )
@@ -83,13 +110,10 @@ await ExecuteMove(RelaxedStance
83
110
await ExecuteMove ( RelaxedStance ) ;
84
111
}
85
112
86
- private async Task ExecuteStep ( Vector2 direction , LegFlags forwardMovingLegs , float distance = 6f , float liftHeight = 2 )
113
+ private async Task ExecuteStep ( Vector2 direction , float angle , LegFlags forwardMovingLegs , float distance = 1f , float liftHeight = 2 )
87
114
{
88
- // identity comparasion to prevent error on float.NaN
89
- if ( ! direction . IsZero ( ) )
90
- {
91
- direction = direction . Normal ( ) ;
92
- }
115
+ _rotationalOdometry += angle ;
116
+ angle = angle / 4 ;
93
117
if ( forwardMovingLegs != LegFlags . LfRrCross && forwardMovingLegs != LegFlags . RfLrCross )
94
118
{
95
119
throw new ArgumentException ( $ "{ nameof ( forwardMovingLegs ) } has to be { nameof ( LegFlags . RfLrCross ) } or { nameof ( LegFlags . LfRrCross ) } ") ;
@@ -100,20 +124,24 @@ private async Task ExecuteStep(Vector2 direction, LegFlags forwardMovingLegs, fl
100
124
// Lift
101
125
var nextStep = RelaxedStance
102
126
. Transform ( new Vector3 ( legShift * direction . X , legShift * direction . Y , liftHeight ) , forwardMovingLegs )
103
- . Transform ( new Vector3 ( - legShift * direction . X , - legShift * direction . Y , 0 ) , backwardsMovingLegs ) ;
127
+ . Rotate ( new Angle ( - angle ) , forwardMovingLegs )
128
+ . Transform ( new Vector3 ( - legShift * direction . X , - legShift * direction . Y , 0 ) , backwardsMovingLegs )
129
+ . Rotate ( new Angle ( angle ) , backwardsMovingLegs ) ;
104
130
await ExecuteMove ( nextStep ) ;
105
131
106
132
// Lower
107
133
nextStep = nextStep
108
134
. Transform ( new Vector3 ( legShift * direction . X , legShift * direction . Y , - liftHeight ) , forwardMovingLegs )
109
- . Transform ( new Vector3 ( - legShift * direction . X , - legShift * direction . Y , 0 ) , backwardsMovingLegs ) ;
135
+ . Rotate ( new Angle ( - angle ) , forwardMovingLegs )
136
+ . Transform ( new Vector3 ( - legShift * direction . X , - legShift * direction . Y , 0 ) , backwardsMovingLegs )
137
+ . Rotate ( new Angle ( angle ) , backwardsMovingLegs ) ;
110
138
await ExecuteMove ( nextStep ) ;
111
139
112
140
// Move all
113
141
nextStep = nextStep . Transform ( new Vector3 ( - legShift * direction . X * 2 , - legShift * direction . Y * 2 , 0 ) ) ;
114
142
await ExecuteMove ( nextStep ) ;
115
143
116
- _odometry += direction * distance ;
144
+ _odometry += Vector2 . Transform ( direction * distance , Quaternion . CreateFromAxisAngle ( Vector3 . UnitZ , _rotationalOdometry . DegreeToRad ( ) ) ) ;
117
145
}
118
146
119
147
private async Task ExecuteMove ( LegPositions targetPosition )
0 commit comments