Steering Wheel Constraint Example¶
This example demonstates the use of aim constraints to simulate how a steering wheel can be used to control the rotation of the front wheels of a car. The scene contains a steering wheel, two front wheels and two green spheres that act as targets for the aim constraints. The steering wheel is connected to a vrTimer object that checks the rotation of the steering wheel and moves the target nodes of the aim constraints accordingly. This causes the front wheels to rotate automatically when the steering wheel is rotated.
The example scene contains four variants that can be selected from the Variant Manager:
- 0-Remove constraints: Removes all constraints from the scene.
- 1-Constrain front wheels: Adds aim constraints to the front wheels and checks for changes in its rotation.
- 2-Turn Left 360: Turns the steering wheel a full circle to the left.
- 3-Return to Center: Turns the steering wheel back to the center, re-aligning the front wheels.
- 4-Turn Right 360: Turns the steering wheel a full circle to the right.
Remove constraints from the steering wheel¶
steering-constraints.vpb (Variant: 0-Remove constraints)¶
1# Removes all constraints
2
3 constraints = vrConstraintService.getConstraints()
4
5 if constraints:
6 for i in constraints:
7 print(f'Removing Constraint: {i}')
8 targets = i.getTargetNodes()
9
10 for j in targets:
11 print(j.getName())
12
13 vrConstraintService.deleteConstraint(i)
14 else:
15 print('No Constraints found.')
16
17 del wheel_timer
Add constraints to the wheels¶
steering-constraints.vpb (Variant: 1-Constrain front wheels)¶
1 # Set up constraints for the wheels and register a function that moves
2 # the targe nodes when the steering wheel has been manually rotated.
3
4 # Store last steering wheel rotation value
5 last_wheel_rotation = 0.0
6
7 # Fetch the required nodes from the scene graph
8 wheel_group = vrNodeService.findNode('Front Wheels')
9 wheel_left = vrNodeService.findNode('Wheel-Left')
10 wheel_right = vrNodeService.findNode('Wheel-Right')
11
12 wheel_target_group = vrNodeService.findNode('Wheel Targets')
13 wheel_left_target = vrNodeService.findNode('Target-Left')
14 wheel_right_target = vrNodeService.findNode('Target-Right')
15
16 # Next create two aim constraints for the wheels. We use the two green spheres
17 # as targets for the wheel_left and wheel_right nodes. That means the wheel nodes will
18 # now rotate automatically to face the position of their target node as long as the
19 # aim constraint is active.
20 lf_constraint = vrConstraintService.createAimConstraint([wheel_left_target], [], wheel_left)
21 rf_constraint = vrConstraintService.createAimConstraint([wheel_right_target], [], wheel_right)
22
23 steering_wheel = vrNodeService.findNode('Steering Wheel')
24
25 # This function checks the steering wheel for manual rotation around the x axis.
26 # For that it is connected to a vrTimer object which calls this function once every frame.
27 # When the wheel is rotated, it translates the wheel targets along the y axis,
28 # causing the wheels to change their rotation because of the aim constraints.
29 def check_steering_wheel_angle():
30 global last_wheel_rotation
31
32 current_rot = round(steering_wheel.getRotationAsEuler().x(), 2)
33
34 if current_rot != last_wheel_rotation: # Don't move when steering wheel stops rotating
35
36 # Lock wheel at maximum rotation angle
37 if current_rot <= -540:
38 steering_wheel.setRotationAsEuler(QVector3D(-540, steering_wheel.getRotationAsEuler().y(), steering_wheel.getRotationAsEuler().z()))
39 elif current_rot >= 540:
40 steering_wheel.setRotationAsEuler(QVector3D(540, steering_wheel.getRotationAsEuler().y(), steering_wheel.getRotationAsEuler().z()))
41
42 else:
43 print(f'Current rotation: {current_rot} / {last_wheel_rotation}')
44
45 delta = abs(round(current_rot - last_wheel_rotation, 2))
46 print(f'Delta: {delta}')
47
48 if current_rot > last_wheel_rotation:
49 wheel_target_group.setTranslation(QVector3D(
50 wheel_target_group.getTranslation().x(),
51 wheel_target_group.getTranslation().y() - delta,
52 wheel_target_group.getTranslation().z())
53 )
54 if current_rot < last_wheel_rotation:
55 wheel_target_group.setTranslation(QVector3D(
56 wheel_target_group.getTranslation().x(),
57 wheel_target_group.getTranslation().y() + delta,
58 wheel_target_group.getTranslation().z())
59 )
60
61 last_wheel_rotation = round(steering_wheel.getRotationAsEuler().x(), 2)
62
63 wheel_timer = vrTimer()
64 wheel_timer.connect(check_steering_wheel_angle)
65 wheel_timer.setActive(True)
66
67 print("Wheels constrained to targets.")
Turn the steering wheel left¶
steering-constraints.vpb (Variant: 2-Turn Left 360)¶
1 # This variant turns the steering wheel to the left.
2 # For that it interpolates the x euler angle between the current
3 # wheel rotation and 360 with a 3 second duration.
4
5 time_in_seconds = 3.0
6 wheel_turn_left = vrInterpolator(True)
7
8 wheel_rot_left = vrRotationSlide(steering_wheel,
9 steering_wheel.getRotationAsEuler().x(),
10 steering_wheel.getRotationAsEuler().y(),
11 steering_wheel.getRotationAsEuler().z(),
12 360,
13 steering_wheel.getRotationAsEuler().y(),
14 steering_wheel.getRotationAsEuler().z(),
15 time_in_seconds)
16
17 wheel_turn_left.add(wheel_rot_left)
18 wheel_turn_left.setActive(True)
Reset the steering wheel to the center¶
steering-constraints.vpb (Variant: 3-Return to Cente)¶
1 # This variant turns the steering wheel back to the center.
2 # It interpolates the x euler angle between the current
3 # wheel rotation and 0 with a 3 second duration.
4
5 time_in_seconds = 3.0
6 wheel_return = vrInterpolator(True)
7
8 # The first three angles are the starting position, the following
9 # three angles are the target position of the rotation
10
11 wheel_rot = vrRotationSlide(steering_wheel,
12 steering_wheel.getRotationAsEuler().x(),
13 steering_wheel.getRotationAsEuler().y(),
14 steering_wheel.getRotationAsEuler().z(),
15 0,
16 steering_wheel.getRotationAsEuler().y(),
17 steering_wheel.getRotationAsEuler().z(),
18 time_in_seconds)
19
20 def align_wheels():
21 # Re-align front wheels
22 wheel_target_group.setTranslation(QVector3D(wheel_target_group.getTranslation().x(), 0.0, wheel_target_group.getTranslation().z()))
23
24 wheel_return.add(wheel_rot)
25 wheel_return.connect(align_wheels)
26 wheel_return.setActive(True)
Turn the steering wheel right¶
steering-constraints.vpb (Variant: 4-Turn Right 360)¶
1 # This variant turns the steering wheel to the right.
2 # For that it interpolates the x euler angle between the current
3 # wheel rotation and -360 with a 3 second duration.
4
5 time_in_seconds = 3.0
6 wheel_turn_right = vrInterpolator(True)
7
8 wheel_rot_right = vrRotationSlide(steering_wheel,
9 steering_wheel.getRotationAsEuler().x(),
10 steering_wheel.getRotationAsEuler().y(),
11 steering_wheel.getRotationAsEuler().z(),
12 -360,
13 steering_wheel.getRotationAsEuler().y(),
14 steering_wheel.getRotationAsEuler().z(),
15 time_in_seconds)
16
17 wheel_turn_right.add(wheel_rot_right)
18 wheel_turn_right.setActive(True)