Gripper Simulation
The example pick_and_place/simulate_gripper shows how the voraus Simulation can be used to simulate a robot’s
interactions with the physical environment – in this example, gripping a box.
The following components are used:
The example is structured similarly to the previous ones. We use a program that can also be executed in a real environment without modification. Another script enables not only the visualization but also the simulation of the gripping process.
In models/, there are simulation classes for the robot, the gripper, and the box, which are loaded into the
voraus Simulation by executing simulation.py.
python3.11 simulate_gripper/simulation.py
1"""Contains the simulation logic, which represents the real system.."""
2
3import sys
4from math import radians
5from pathlib import Path
6
7sys.path.append(str(Path(__file__).parents[1]))
8
9
10if __name__ == "__main__":
11 from simulate_gripper.models import Box, Gripper, Robot
12 from voraus_3d_visu import Visu
13 from voraus_simulation import Simulation, StaticObject
14
15 simulation = Simulation(frequency=50, visualization=Visu("http://voraus-3d-visu/", clear_all=True))
16 robot = Robot("opc.tcp://voraus-core:48401/", [0, 0, 0.3], rotation=[0, 0, radians(-20)])
17
18 with simulation.run(), robot.connection():
19 StaticObject(glb_file=None, urdf_path=Path("plane_transparent.urdf"))
20
21 gripper = Gripper()
22 box = Box([0.6, 0.1, 0.2], rotation=[0, 0, radians(15)])
23
24 while True:
25 robot.get_robot_data()
26
27 grasp = robot.robot_data.digital_outputs[1]
28 gripper.update(robot.robot_data.world_flange_pose, grasping=grasp)
29
30 simulation.step()
31 simulation.sleep()
Behavior and functionality are implemented individually for each simulation object. The box does not contain any special features. It is a passive simulation object that is loaded into the simulation via an OBJ file using URDF (Unified Robot Description Format). To display a box in the voraus 3D Visu, the simulation object is also initialized with a GLB. The position and orientation are updated in the background by the simulation.
1"""Contains a box simulation model."""
2
3from pathlib import Path
4
5from voraus_simulation import DynamicObject
6
7models = Path(__file__).parents[2] / "assets/box"
8
9
10class Box(DynamicObject):
11 """Defines a box simulation model."""
12
13 def __init__(self, position: list[float] | None = None, rotation: list[float] | None = None) -> None:
14 """Initializes a box simulation model.
15
16 Args:
17 position: The initial position of the box. Defaults to None.
18 rotation: The initial rotation of the box. Defaults to None.
19 """
20 glb_path = models / "box.glb"
21 urdf_path = models / "box.urdf"
22 super().__init__(glb_path, urdf_path, position, rotation)
The gripper simulation object from models/gripper.py has to be updated based on the robot position.
To do this, it is given an update method that creates so-called constraints to the flange pose. Furthermore, the update
method contains the logic for gripping objects. If the gripper is to grip, contact points are calculated by the
simulation, and a constraint to the touched object is created as well. If the gripper pose changes, the pose of the
object connected via the constraint also changes. This simulates a gripping process.
The robot itself is not loaded into the simulation engine in this example. However, we use the voraus Simulation to
automatically load the static visualization objects into the voraus 3D Visu. In models/robot.py, a cube on
which the robot is mounted is defined in addition to the robot object. Besides the visualization logic,
the robot instance also contains methods for communicating with the voraus.core.
Our program is defined in program.py. When it is executed, a tool offset is set. After you press Enter,
the robot moves to the gripping pose.
python3.11 simulate_gripper/program.py
1# pylint: disable=protected-access
2"""Contains the program which controls the robot."""
3
4from math import radians
5
6from voraus_robot_arm import CartesianPose, JointPose, VorausIndustrialRobotArm, y
7
8home = JointPose(0, -1.57, 1.57, -1.57, -1.57, 0)
9scan = JointPose(radians(-63), radians(-131), radians(80), radians(-80), radians(-60), radians(-10))
10pre_pick = CartesianPose(0.5, 0.3, -0.05, -radians(180), 0, -radians(180))
11pick = CartesianPose(0.5, 0.3, -0.128, -radians(180), 0, -radians(180))
12offset = -0.6
13
14
15if __name__ == "__main__":
16 robot = VorausIndustrialRobotArm()
17
18 with robot.connect("voraus-core", port=48401):
19 robot._driver._objects.robot.commands.tool.set_tool_transformation_offset((0, 0, 0.103, 0, 0, 0))
20 tool_control_output = robot.get_digital_output_v(2)
21 robot.enable()
22
23 input("Press <enter> to pick the box.")
24 robot.move_ptp(pre_pick)
25 robot.move_linear(pick).result()
26 tool_control_output.set()
27
28 robot.move_ptp(scan)
29
30 input("Press <enter> to place the box.")
31 robot.move_ptp(pre_pick + y(offset)).result()
32 tool_control_output.clear()
We set digital output 2 to high to trigger a gripping process. The gripper in our simulation listens to this output and grips the box. The robot then moves to the position shown in Fig. 29.
After you press Enter again, the robot moves to the place pose and sets the box down again by setting digital output 2 to low, as shown in Fig. 30.
Fig. 30 Simulated box poses after the program has been executed