Skip to content

Commit 25537e0

Browse files
authored
Merge pull request #131 from DeepBlueRobotics/add-PoweredHinge2Joint
Add PoweredHinge2Joint
2 parents 1e28b1e + af8a0ce commit 25537e0

File tree

14 files changed

+324
-236
lines changed

14 files changed

+324
-236
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ jobs:
3232

3333
- name: Setup Webots
3434
id: setupWebots
35-
uses: DeepBlueRobotics/setup-webots@v2.0.3
35+
uses: DeepBlueRobotics/setup-webots@v2.1
3636
with:
37-
webotsVersion: R2023b
37+
webotsVersion: R2024a
38+
webotsRepository: DeepBlueRobotics/webots
39+
webotsTag: R2024a_DeepBlueSim_2024_07_29
3840

3941
- name: Do the system test
4042
uses: ./.github/actions/run-system-test
@@ -80,9 +82,11 @@ jobs:
8082

8183
- name: Setup Webots
8284
id: setupWebots
83-
uses: DeepBlueRobotics/setup-webots@v2
85+
uses: DeepBlueRobotics/setup-webots@v2.1
8486
with:
85-
webotsVersion: R2023b
87+
webotsVersion: R2024a
88+
webotsRepository: DeepBlueRobotics/webots
89+
webotsTag: R2024a_DeepBlueSim_2024_07_29
8690

8791
- name: Checkout source
8892
uses: actions/checkout@v4

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ advantage of the WPILib's WebSockets server desktop simulation extension.
2222

2323
### Installation
2424

25-
1. Install Webots if you don't already have it installed.
25+
1. Install the latest [official nightly build of Webots](https://github.com/cyberbotics/webots/releases).
2626
1. Add the DeepBlueSim Gradle plugin to your `build.gradle` by adding the following line
2727
in your `plugins` section:
2828
```

example/src/systemTest/java/frc/robot/SystemTestRobot.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void testDrivesToLocationAndElevatesInAutonomous() throws Exception {
2828
0.1, "Robot close to target velocity");
2929
assertEquals(0.0,
3030
Units.radiansToDegrees(
31-
s.angularVelocity("ROBOT").getAngle()),
31+
s.angularVelocity("ROBOT").norm()),
3232
1, "Robot close to target angular velocity");
3333
}).atSec(3.0, s -> {
3434
assertEquals(0.0,
@@ -45,7 +45,7 @@ void testDrivesToLocationAndElevatesInAutonomous() throws Exception {
4545
0.05, "Robot close to target velocity");
4646
assertEquals(0.0,
4747
Units.radiansToDegrees(
48-
s.angularVelocity("ROBOT").getAngle()),
48+
s.angularVelocity("ROBOT").norm()),
4949
1, "Robot close to target angular velocity");
5050
}).run();
5151
}
@@ -78,10 +78,10 @@ void testCanBeRotatedInPlaceInTeleop() throws Exception {
7878
.getDistance(new Translation3d(0, 0, 0)),
7979
0.1, "Robot close to target velocity");
8080
assertEquals(63.9, Units.radiansToDegrees(
81-
s.angularVelocity("ROBOT").getAngle()),
82-
5.0, "Robot close to target angular velocity");
81+
s.angularVelocity("ROBOT").norm()), 5.0,
82+
"Robot close to target angular velocity");
8383
assertEquals(0.0,
84-
new Translation3d(s.angularVelocity("ROBOT").getAxis())
84+
new Translation3d(s.angularVelocity("ROBOT").unit())
8585
.getDistance(new Translation3d(0, 0, 1)),
8686
0.1, "Robot close to target angular velocity axis");
8787
}).atSec(1.5, s -> {
@@ -96,7 +96,7 @@ void testCanBeRotatedInPlaceInTeleop() throws Exception {
9696
0.1, "Robot close to target velocity");
9797
assertEquals(0.0,
9898
Units.radiansToDegrees(
99-
s.angularVelocity("ROBOT").getAngle()),
99+
s.angularVelocity("ROBOT").norm()),
100100
1, "Robot close to target angular velocity");
101101
}).run();
102102
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#VRML_SIM R2023b utf8
2+
# license: MIT
3+
# license url: https://github.com/DeepBlueRobotics/DeepBlueSim/blob/master/LICENSE.md
4+
# template language: javascript
5+
# A HingeJoint powered by a DeepBlueSim-compatible motor
6+
7+
EXTERNPROTO "DBSRotationalMotorBase.proto"
8+
EXTERNPROTO "PreconfiguredDBSRotationalMotor.proto"
9+
10+
EXTERNPROTO "CANCoder.proto"
11+
EXTERNPROTO "DBSQuadratureEncoder.proto"
12+
EXTERNPROTO "REVBuiltinEncoder.proto"
13+
EXTERNPROTO "SparkMaxAbsoluteEncoder.proto"
14+
EXTERNPROTO "SparkMaxAlternateEncoder.proto"
15+
EXTERNPROTO "SparkMaxAnalogSensor.proto"
16+
17+
EXTERNPROTO "DBSBrake.proto"
18+
19+
PROTO PoweredHinge2Joint [
20+
field MFNode{
21+
DBSRotationalMotorBase{}, PreconfiguredDBSRotationalMotor{}
22+
CANCoder{}, DBSQuadratureEncoder{}, REVBuiltinEncoder{}, SparkMaxAbsoluteEncoder{}, SparkMaxAlternateEncoder{}, SparkMaxAnalogSensor{},
23+
DBSBrake{}
24+
} devices [PreconfiguredDBSRotationalMotor{} REVBuiltinEncoder{} DBSBrake{}]
25+
field MFNode{
26+
DBSRotationalMotorBase{}, PreconfiguredDBSRotationalMotor{}
27+
CANCoder{}, DBSQuadratureEncoder{}, REVBuiltinEncoder{}, SparkMaxAbsoluteEncoder{}, SparkMaxAlternateEncoder{}, SparkMaxAnalogSensor{},
28+
DBSBrake{}
29+
} devices2 [PreconfiguredDBSRotationalMotor{} REVBuiltinEncoder{} DBSBrake{}]
30+
field SFNode{Solid{}} endPoint Solid{}
31+
field SFNode{HingeJointParameters{}} jointParameters HingeJointParameters{}
32+
field SFNode{JointParameters{}} jointParameters2 JointParameters{}
33+
]
34+
{
35+
%<
36+
import {assert} from 'wbutility.js';
37+
let dbsutility = eval(wbfile.readTextFile(`${context.project_path}protos/deepbluesim/dbsutility.js`));
38+
dbsutility.assertValidPoweredJointDevices(fields.devices.value, "PoweredHinge2Joint.devices", assert);
39+
dbsutility.assertValidPoweredJointDevices(fields.devices2.value, "PoweredHinge2Joint.devices2", assert);
40+
>%
41+
Hinge2Joint {
42+
device IS devices
43+
device2 IS devices2
44+
endPoint IS endPoint
45+
jointParameters IS jointParameters
46+
jointParameters2 IS jointParameters2
47+
}
48+
}

plugin/controller/src/webotsFolder/dist/protos/deepbluesim/PoweredHingeJoint.proto

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,9 @@ PROTO PoweredHingeJoint [
2828
{
2929
%<
3030
import {assert} from 'wbutility.js';
31-
let devices = fields.devices.value;
32-
let hasBrake = false;
33-
let motorDevice = null;
34-
let encoderDevice = null;
35-
for (let i = 0; i < devices.length; i++) {
36-
let node_name = devices[i].node_name;
37-
if (node_name.endsWith("Brake")) {
38-
hasBrake = true;
39-
} else if (node_name.endsWith("Motor")) {
40-
motorDevice = devices[i];
41-
} else if (node_name.endsWith("Encoder")) {
42-
encoderDevice = devices[i];
43-
}
44-
}
45-
assert(hasBrake, "PoweredHingeJoint is missing the required DBSBrake device!");
46-
assert(motorDevice !== null, "PoweredHingeJoint is missing the required motor device!");
47-
let motorType = motorDevice?.node_name;
48-
let controllerType = motorDevice?.fields.controllerType.value;
49-
if (controllerType?.startsWith("Spark")) {
50-
assert(encoderDevice !== null, "PoweredHingeJoint is using a " + controllerType + " motor controller but is missing the required encoder device! "
51-
+ "Consider adding a REVBuiltinEncoder.");
52-
} else if (controllerType === "PWM") {
53-
let encoderType = encoderDevice?.node_name;
54-
assert(!encoderType?.endsWith("BuiltinEncoder"), "PoweredHingeJoint is using a " + controllerType + " motor controller, so a built-in encoder is not allowed!");
55-
}
31+
let dbsutility = eval(wbfile.readTextFile(`${context.project_path}protos/deepbluesim/dbsutility.js`));
32+
dbsutility.assertValidPoweredJointDevices(fields.devices.value, "PoweredHingeJoint.devices", assert);
33+
5634
>%
5735
HingeJoint {
5836
device IS devices

plugin/controller/src/webotsFolder/dist/protos/deepbluesim/PoweredSliderJoint.proto

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,8 @@ PROTO PoweredSliderJoint [
2828
{
2929
%<
3030
import {assert} from 'wbutility.js';
31-
let devices = fields.devices.value;
32-
let hasBrake = false;
33-
let motorDevice = null;
34-
let encoderDevice = null;
35-
for (let i = 0; i < devices.length; i++) {
36-
let node_name = devices[i].node_name;
37-
if (node_name.endsWith("Brake")) {
38-
hasBrake = true;
39-
} else if (node_name.endsWith("Motor")) {
40-
motorDevice = devices[i];
41-
} else if (node_name.endsWith("Encoder")) {
42-
encoderDevice = devices[i];
43-
}
44-
}
45-
assert(hasBrake, "PoweredSliderJoint is missing the required DBSBrake device!");
46-
assert(motorDevice !== null, "PoweredSliderJoint is missing the required motor device!");
47-
let motorType = motorDevice?.node_name;
48-
let controllerType = motorDevice?.fields.controllerType.value;
49-
if (controllerType?.startsWith("Spark")) {
50-
assert(encoderDevice !== null, "PoweredSliderJoint is using a " + controllerType + " motor controller but is missing the required encoder device! "
51-
+ "Consider adding a REVBuiltinEncoder.");
52-
} else if (controllerType === "PWM") {
53-
let encoderType = encoderDevice?.node_name;
54-
assert(!encoderType?.endsWith("BuiltinEncoder"), "PoweredSliderJoint is using a " + controllerType + " motor controller, so a built-in encoder is not allowed!");
55-
}
31+
let dbsutility = eval(wbfile.readTextFile(`${context.project_path}protos/deepbluesim/dbsutility.js`));
32+
dbsutility.assertValidPoweredJointDevices(fields.devices.value, "PoweredSliderJoint.devices", assert);
5633
>%
5734
SliderJoint {
5835
device IS devices
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
({
2+
assertValidPoweredJointDevices: function (devices, fieldDesc, assert) {
3+
let hasBrake = false;
4+
let motorDevice = null;
5+
let encoderDevice = null;
6+
for (let i = 0; i < devices.length; i++) {
7+
let node_name = devices[i].node_name;
8+
if (node_name.endsWith("Brake")) {
9+
hasBrake = true;
10+
} else if (node_name.endsWith("Motor")) {
11+
motorDevice = devices[i];
12+
} else if (node_name.endsWith("Encoder")) {
13+
encoderDevice = devices[i];
14+
}
15+
}
16+
assert(hasBrake, fieldDesc + " is missing the required DBSBrake device!");
17+
assert(motorDevice !== null, fieldDesc + " is missing the required motor device!");
18+
let motorType = motorDevice?.node_name;
19+
let controllerType = motorDevice?.fields.controllerType.value;
20+
if (controllerType?.startsWith("Spark")) {
21+
assert(encoderDevice !== null, fieldDesc + " is using a " + controllerType + " motor controller but is missing the required encoder device! "
22+
+ "Consider adding a REVBuiltinEncoder.");
23+
} else if (controllerType === "PWM") {
24+
let encoderType = encoderDevice?.node_name;
25+
assert(!encoderType?.endsWith("BuiltinEncoder"), fieldDesc + " is using a " + controllerType + " motor controller, so a built-in encoder is not allowed!");
26+
}
27+
},
28+
})
Loading

plugin/controller/src/webotsFolder/dist/worlds/MotorController.wbt

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#VRML_SIM R2023b utf8
1+
#VRML_SIM R2024a utf8
22

33
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2023b/projects/objects/backgrounds/protos/TexturedBackground.proto"
44
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2023b/projects/objects/backgrounds/protos/TexturedBackgroundLight.proto"
@@ -7,12 +7,13 @@ EXTERNPROTO "../protos/deepbluesim/PoweredHingeJoint.proto"
77
EXTERNPROTO "../protos/deepbluesim/PreconfiguredDBSRotationalMotor.proto"
88
EXTERNPROTO "../protos/deepbluesim/DBSBrake.proto"
99
EXTERNPROTO "../protos/deepbluesim/REVBuiltinEncoder.proto"
10+
EXTERNPROTO "../protos/deepbluesim/PoweredHinge2Joint.proto"
1011

1112
WorldInfo {
1213
}
1314
Viewpoint {
1415
orientation -0.24402898166491363 0.33039742727224586 0.9117496345814823 1.5165266004776918
15-
position -0.6005906535473244 -4.740227792969629 3.113219051699273
16+
position -1.136298742206523 -8.781932059872242 5.731292223532602
1617
}
1718
TexturedBackground {
1819
}
@@ -60,6 +61,78 @@ DEF ROBOT Robot {
6061
}
6162
]
6263
}
64+
DEF HINGE2JOINT Solid {
65+
translation 0 -2 0
66+
rotation 0 1 0 0
67+
children [
68+
DEF HINGE2JOINT_BASE Pose {
69+
children [
70+
Shape {
71+
appearance PBRAppearance {
72+
}
73+
geometry Box {
74+
size 1 1 0.1
75+
}
76+
}
77+
]
78+
}
79+
PoweredHinge2Joint {
80+
devices [
81+
PreconfiguredDBSRotationalMotor {
82+
motorType "MiniCIM"
83+
controllerType "PWM"
84+
port 2
85+
gearing 97.3333
86+
}
87+
DBSBrake {
88+
}
89+
]
90+
devices2 [
91+
PreconfiguredDBSRotationalMotor {
92+
motorType "MiniCIM"
93+
controllerType "PWM"
94+
port 3
95+
gearing 97.3333
96+
}
97+
DBSBrake {
98+
}
99+
]
100+
endPoint DEF HINGE2JOINT_SHAFT Solid {
101+
translation 0 0 2
102+
children [
103+
DEF HINGE2JOINT_SHAFT_GEOM Pose {
104+
rotation 0 1 0 1.5701
105+
children [
106+
Shape {
107+
appearance PBRAppearance {
108+
}
109+
geometry Cylinder {
110+
height 0.215
111+
radius 0.5
112+
subdivision 8
113+
}
114+
}
115+
]
116+
}
117+
]
118+
boundingObject USE HINGE2JOINT_SHAFT_GEOM
119+
physics Physics {
120+
}
121+
}
122+
jointParameters HingeJointParameters {
123+
axis 0 1 0
124+
anchor 0 0 2
125+
}
126+
jointParameters2 JointParameters {
127+
axis 1 0 0
128+
}
129+
}
130+
]
131+
name "solid(3)"
132+
boundingObject USE HINGE2JOINT_BASE
133+
physics Physics {
134+
}
135+
}
63136
DEF NEO_BASE Solid {
64137
translation 0 2 0
65138
children [

plugin/libdeepbluesim/src/main/java/org/carlmontrobotics/libdeepbluesim/Watcher.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99

1010
import org.carlmontrobotics.libdeepbluesim.internal.NTConstants;
1111

12+
import edu.wpi.first.math.VecBuilder;
13+
import edu.wpi.first.math.Vector;
1214
import edu.wpi.first.math.geometry.Rotation3d;
1315
import edu.wpi.first.math.geometry.Translation3d;
16+
import edu.wpi.first.math.numbers.N3;
1417
import edu.wpi.first.networktables.DoubleArrayPublisher;
1518
import edu.wpi.first.networktables.DoubleArrayTopic;
1619
import edu.wpi.first.networktables.NetworkTable;
@@ -40,7 +43,8 @@ class Watcher {
4043
private volatile CompletableFuture<Void> velocityReady =
4144
new CompletableFuture<>();
4245
private volatile Translation3d position = null, velocity = null;
43-
private volatile Rotation3d rotation = null, angularVelocity = null;
46+
private volatile Vector<N3> angularVelocity = null;
47+
private volatile Rotation3d rotation = null;
4448
private final NetworkTableInstance inst;
4549
private final String defPath;
4650
private final NetworkTable table;
@@ -106,8 +110,8 @@ private Watcher(String defPath) {
106110
value.valueData.value.getDoubleArray();
107111
velocity = new Translation3d(velAsArray[0],
108112
velAsArray[1], velAsArray[2]);
109-
angularVelocity = new Rotation3d(velAsArray[3],
110-
velAsArray[4], velAsArray[5]);
113+
angularVelocity = VecBuilder.fill(velAsArray[3],
114+
velAsArray[4], velAsArray[5]);
111115
velocityReady.complete(null);
112116
break;
113117
}
@@ -204,7 +208,7 @@ Rotation3d getRotation() {
204208
*
205209
* @return the node's angular velocity.
206210
*/
207-
Rotation3d getAngularVelocity() {
211+
Vector<N3> getAngularVelocity() {
208212
if (!inst.isConnected()) {
209213
LOG.log(Level.DEBUG,
210214
"NetworkTables is not connected, so starting server");

plugin/libdeepbluesim/src/main/java/org/carlmontrobotics/libdeepbluesim/WebotsSimulator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
import edu.wpi.first.hal.HAL;
3232
import edu.wpi.first.hal.SimDevice;
3333
import edu.wpi.first.hal.SimDouble;
34+
import edu.wpi.first.math.Vector;
3435
import edu.wpi.first.math.geometry.Rotation3d;
3536
import edu.wpi.first.math.geometry.Translation3d;
37+
import edu.wpi.first.math.numbers.N3;
3638
import edu.wpi.first.networktables.LogMessage;
3739
import edu.wpi.first.networktables.NetworkTable;
3840
import edu.wpi.first.networktables.NetworkTableEvent.Kind;
@@ -673,11 +675,11 @@ public Rotation3d rotation(String defPath) {
673675

674676
/**
675677
* Gets the angular velocity of a specific node in the simulated world.
676-
*
678+
*
677679
* @param defPath the DEF path to the Webots node to get the position of.
678680
* @return the angular velocity of the requested node.
679681
*/
680-
public Rotation3d angularVelocity(String defPath) {
682+
public Vector<N3> angularVelocity(String defPath) {
681683
// ntTransientLogLevel = LogMessage.kDebug4;
682684
try {
683685
var watcher = Watcher.getByDefPath(defPath);

0 commit comments

Comments
 (0)