urkit 0.3.7__tar.gz → 0.3.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {urkit-0.3.7 → urkit-0.3.8}/PKG-INFO +10 -7
  2. {urkit-0.3.7 → urkit-0.3.8}/README.md +9 -6
  3. {urkit-0.3.7 → urkit-0.3.8}/pyproject.toml +1 -1
  4. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/__init__.py +1 -1
  5. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/robot.py +109 -20
  6. {urkit-0.3.7 → urkit-0.3.8}/src/urkit.egg-info/PKG-INFO +10 -7
  7. {urkit-0.3.7 → urkit-0.3.8}/setup.cfg +0 -0
  8. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/__main__.py +0 -0
  9. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/cli/__init__.py +0 -0
  10. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/cli/colors.py +0 -0
  11. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/cli/connection_monitor.py +0 -0
  12. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/cli/points.py +0 -0
  13. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/cli/teach.py +0 -0
  14. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/config.py +0 -0
  15. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/connection.py +0 -0
  16. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/exceptions.py +0 -0
  17. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/geometry.py +0 -0
  18. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/gripper/__init__.py +0 -0
  19. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/gripper/base.py +0 -0
  20. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/gripper/digital.py +0 -0
  21. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/gripper/presets.py +0 -0
  22. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/gripper/robotiq.py +0 -0
  23. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/gripper/robotiq_preamble.py +0 -0
  24. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/io.py +0 -0
  25. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/motion.py +0 -0
  26. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/points.py +0 -0
  27. {urkit-0.3.7 → urkit-0.3.8}/src/urkit/telemetry.py +0 -0
  28. {urkit-0.3.7 → urkit-0.3.8}/src/urkit.egg-info/SOURCES.txt +0 -0
  29. {urkit-0.3.7 → urkit-0.3.8}/src/urkit.egg-info/dependency_links.txt +0 -0
  30. {urkit-0.3.7 → urkit-0.3.8}/src/urkit.egg-info/entry_points.txt +0 -0
  31. {urkit-0.3.7 → urkit-0.3.8}/src/urkit.egg-info/requires.txt +0 -0
  32. {urkit-0.3.7 → urkit-0.3.8}/src/urkit.egg-info/top_level.txt +0 -0
  33. {urkit-0.3.7 → urkit-0.3.8}/tests/test_exceptions.py +0 -0
  34. {urkit-0.3.7 → urkit-0.3.8}/tests/test_geometry.py +0 -0
  35. {urkit-0.3.7 → urkit-0.3.8}/tests/test_gripper.py +0 -0
  36. {urkit-0.3.7 → urkit-0.3.8}/tests/test_gripper_factory.py +0 -0
  37. {urkit-0.3.7 → urkit-0.3.8}/tests/test_gripper_presets.py +0 -0
  38. {urkit-0.3.7 → urkit-0.3.8}/tests/test_points.py +0 -0
  39. {urkit-0.3.7 → urkit-0.3.8}/tests/test_robot_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.7
3
+ Version: 0.3.8
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -88,7 +88,7 @@ robot = URRobot(ip="192.168.1.50", points="points.db", gripper=ROBOTIQ_HAND_E)
88
88
  robot.gripper.activate()
89
89
 
90
90
  robot.move_to("home")
91
- robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0])
91
+ robot.move_to("pick", offset_z=0.05) # 5cm above
92
92
  robot.gripper.close()
93
93
  robot.move_to("place")
94
94
  robot.gripper.open()
@@ -394,10 +394,12 @@ A pose is `[x, y, z, rx, ry, rz]`: position in meters and orientation as a **rot
394
394
 
395
395
  #### Offsets
396
396
 
397
- Offsets are 6-element lists `[dx, dy, dz, drx, dry, drz]`:
397
+ Offsets can use individual parameters or a full 6-element list:
398
398
 
399
399
  ```python
400
- robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0]) # 5cm above pick
400
+ robot.move_to("pick", offset_z=0.05) # 5cm above
401
+ robot.move_to("pick", offset_x=0.01, offset_z=-0.02) # combined
402
+ robot.move_to("pick", offset=[0, 0, 0.05, 0, 0.1, 0]) # full with rotation
401
403
  ```
402
404
 
403
405
  #### Resolve a Pose
@@ -416,7 +418,7 @@ robot.move_to(pose) # move to the resolved pose later
416
418
  from urkit import MoveFrame
417
419
 
418
420
  robot.move_frame = MoveFrame.TOOL # default is BASE
419
- robot.move_relative([0, 0, 0.05, 0, 0, 0]) # 5cm along tool Z
421
+ robot.move_relative(delta_z=0.05) # 5cm along tool Z
420
422
  ```
421
423
 
422
424
  - **BASE** (default): delta relative to robot base
@@ -440,8 +442,9 @@ robot.import_points("backup.json")
440
442
  #### Relative Moves
441
443
 
442
444
  ```python
443
- robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
444
- robot.move_relative([0, 0, 0.05, 0, 0, 0], frame=MoveFrame.TOOL) # 5cm along tool Z
445
+ robot.move_relative(delta_y=0.01) # 1cm along Y
446
+ robot.move_relative(delta_z=0.05, frame=MoveFrame.TOOL) # 5cm along tool Z
447
+ robot.move_relative([0, 0.01, 0, 0, 0, 0])
445
448
  ```
446
449
 
447
450
  #### Sequences with Blending
@@ -62,7 +62,7 @@ robot = URRobot(ip="192.168.1.50", points="points.db", gripper=ROBOTIQ_HAND_E)
62
62
  robot.gripper.activate()
63
63
 
64
64
  robot.move_to("home")
65
- robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0])
65
+ robot.move_to("pick", offset_z=0.05) # 5cm above
66
66
  robot.gripper.close()
67
67
  robot.move_to("place")
68
68
  robot.gripper.open()
@@ -368,10 +368,12 @@ A pose is `[x, y, z, rx, ry, rz]`: position in meters and orientation as a **rot
368
368
 
369
369
  #### Offsets
370
370
 
371
- Offsets are 6-element lists `[dx, dy, dz, drx, dry, drz]`:
371
+ Offsets can use individual parameters or a full 6-element list:
372
372
 
373
373
  ```python
374
- robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0]) # 5cm above pick
374
+ robot.move_to("pick", offset_z=0.05) # 5cm above
375
+ robot.move_to("pick", offset_x=0.01, offset_z=-0.02) # combined
376
+ robot.move_to("pick", offset=[0, 0, 0.05, 0, 0.1, 0]) # full with rotation
375
377
  ```
376
378
 
377
379
  #### Resolve a Pose
@@ -390,7 +392,7 @@ robot.move_to(pose) # move to the resolved pose later
390
392
  from urkit import MoveFrame
391
393
 
392
394
  robot.move_frame = MoveFrame.TOOL # default is BASE
393
- robot.move_relative([0, 0, 0.05, 0, 0, 0]) # 5cm along tool Z
395
+ robot.move_relative(delta_z=0.05) # 5cm along tool Z
394
396
  ```
395
397
 
396
398
  - **BASE** (default): delta relative to robot base
@@ -414,8 +416,9 @@ robot.import_points("backup.json")
414
416
  #### Relative Moves
415
417
 
416
418
  ```python
417
- robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
418
- robot.move_relative([0, 0, 0.05, 0, 0, 0], frame=MoveFrame.TOOL) # 5cm along tool Z
419
+ robot.move_relative(delta_y=0.01) # 1cm along Y
420
+ robot.move_relative(delta_z=0.05, frame=MoveFrame.TOOL) # 5cm along tool Z
421
+ robot.move_relative([0, 0.01, 0, 0, 0, 0])
419
422
  ```
420
423
 
421
424
  #### Sequences with Blending
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "urkit"
7
- version = "0.3.7"
7
+ version = "0.3.8"
8
8
  description = "Universal Robots e-Series control toolkit built on ur_rtde"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -24,7 +24,7 @@ Quick start::
24
24
 
25
25
  from __future__ import annotations
26
26
 
27
- __version__ = "0.3.7"
27
+ __version__ = "0.3.8"
28
28
 
29
29
  from urkit.config import load_config, resolve_config
30
30
  from urkit.exceptions import (
@@ -438,7 +438,7 @@ class URRobot:
438
438
  Example:
439
439
  >>> robot.move_frame = MoveFrame.TOOL
440
440
  >>> robot.move_relative([0.01, 0, 0, 0, 0, 0]) # +X in tool frame
441
- >>> robot.move_to("pick", offset=[0, 0, 0.05]) # offset in tool frame
441
+ >>> robot.move_to("pick", offset_z=0.05) # offset in tool frame
442
442
  """
443
443
  return self._move_frame
444
444
 
@@ -821,6 +821,12 @@ class URRobot:
821
821
  *,
822
822
  offset: list[float] | None = None,
823
823
  frame: MoveFrame | None = None,
824
+ offset_x: float = 0.0,
825
+ offset_y: float = 0.0,
826
+ offset_z: float = 0.0,
827
+ offset_rx: float = 0.0,
828
+ offset_ry: float = 0.0,
829
+ offset_rz: float = 0.0,
824
830
  ) -> list[float]:
825
831
  """Resolve a saved point or raw pose to a TCP pose.
826
832
 
@@ -831,9 +837,16 @@ class URRobot:
831
837
  target: A saved point name (str) or a raw TCP pose
832
838
  [x, y, z, rx, ry, rz].
833
839
  offset: Optional offset [dx, dy, dz, drx, dry, drz]
834
- applied to the target pose.
840
+ applied to the target pose. Mutually exclusive with
841
+ individual offset_* parameters.
835
842
  frame: Coordinate frame for the offset. Falls back to the
836
843
  current ``move_frame`` property (BASE or TOOL).
844
+ offset_x: X offset in meters (default 0.0).
845
+ offset_y: Y offset in meters (default 0.0).
846
+ offset_z: Z offset in meters (default 0.0).
847
+ offset_rx: Roll offset in radians (default 0.0).
848
+ offset_ry: Pitch offset in radians (default 0.0).
849
+ offset_rz: Yaw offset in radians (default 0.0).
837
850
 
838
851
  Returns:
839
852
  TCP pose as [x, y, z, rx, ry, rz].
@@ -843,18 +856,32 @@ class URRobot:
843
856
 
844
857
  Example:
845
858
  >>> pose = robot.get_pose("pick")
846
- >>> pose = robot.get_pose("pick", offset=[0, 0, 0.05, 0, 0, 0])
859
+ >>> pose = robot.get_pose("pick", offset_z=0.05)
847
860
  >>> robot.move_to(pose)
848
861
  """
849
862
  point = self._lookup_point(target)
850
863
 
851
- if offset is not None:
852
- if len(offset) != 6:
864
+ # Build offset from individual params or use provided list
865
+ individual_offset = [offset_x, offset_y, offset_z, offset_rx, offset_ry, offset_rz]
866
+ has_individual = any(v != 0.0 for v in individual_offset)
867
+
868
+ if offset is not None and has_individual:
869
+ raise PointError(
870
+ "Cannot use both 'offset' list and individual offset_* parameters. "
871
+ "Use one or the other."
872
+ )
873
+
874
+ final_offset = offset if offset is not None and not has_individual else (
875
+ individual_offset if has_individual else None
876
+ )
877
+
878
+ if final_offset is not None:
879
+ if len(final_offset) != 6:
853
880
  raise PointError(
854
881
  f"Offset must have 6 values [dx, dy, dz, drx, dry, drz], "
855
- f"got {len(offset)}."
882
+ f"got {len(final_offset)}."
856
883
  )
857
- point = point.with_offset(offset, frame=frame or self._move_frame)
884
+ point = point.with_offset(final_offset, frame=frame or self._move_frame)
858
885
 
859
886
  return list(point.pose)
860
887
 
@@ -868,6 +895,12 @@ class URRobot:
868
895
  vel: float | None = None,
869
896
  acc: float | None = None,
870
897
  asynchronous: bool = False,
898
+ offset_x: float = 0.0,
899
+ offset_y: float = 0.0,
900
+ offset_z: float = 0.0,
901
+ offset_rx: float = 0.0,
902
+ offset_ry: float = 0.0,
903
+ offset_rz: float = 0.0,
871
904
  ) -> None:
872
905
  """Move to a saved point or raw pose.
873
906
 
@@ -877,11 +910,18 @@ class URRobot:
877
910
  linear: If True (default), use Cartesian linear move (moveL).
878
911
  If False, use joint-space move (moveJ).
879
912
  offset: Optional offset [dx, dy, dz, drx, dry, drz]
880
- applied to the target pose before moving.
913
+ applied to the target pose before moving. Mutually
914
+ exclusive with individual offset_* parameters.
881
915
  frame: Coordinate frame for the offset. Falls back to the
882
916
  current ``move_frame`` property (BASE or TOOL).
883
917
  vel: Velocity override. Falls back to default_vel.
884
918
  acc: Acceleration override. Falls back to default_acc.
919
+ offset_x: X offset in meters (default 0.0).
920
+ offset_y: Y offset in meters (default 0.0).
921
+ offset_z: Z offset in meters (default 0.0).
922
+ offset_rx: Roll offset in radians (default 0.0).
923
+ offset_ry: Pitch offset in radians (default 0.0).
924
+ offset_rz: Yaw offset in radians (default 0.0).
885
925
 
886
926
  Raises:
887
927
  MotionError: If the move fails or IK has no solution.
@@ -890,8 +930,9 @@ class URRobot:
890
930
  Example:
891
931
  >>> robot.move_to("home")
892
932
  >>> robot.move_to("pick", linear=False)
893
- >>> robot.move_to("place", offset=[0, 0, 0.05, 0, 0, 0])
894
- >>> robot.move_to("place", offset=[0, 0, 0.05], frame=MoveFrame.TOOL)
933
+ >>> robot.move_to("pick", offset_z=0.05) # 5cm above
934
+ >>> robot.move_to("pick", offset_x=0.01, offset_z=-0.02)
935
+ >>> robot.move_to("pick", offset=[0, 0, 0.05, 0, 0.1, 0]) # full
895
936
  >>> robot.move_to([0.5, 0, 0.3, 0, 0, 0]) # raw pose
896
937
  """
897
938
  self._check_connection()
@@ -899,14 +940,28 @@ class URRobot:
899
940
 
900
941
  point = self._lookup_point(target)
901
942
 
943
+ # Build offset from individual params or use provided list
944
+ individual_offset = [offset_x, offset_y, offset_z, offset_rx, offset_ry, offset_rz]
945
+ has_individual = any(v != 0.0 for v in individual_offset)
946
+
947
+ if offset is not None and has_individual:
948
+ raise PointError(
949
+ "Cannot use both 'offset' list and individual offset_* parameters. "
950
+ "Use one or the other."
951
+ )
952
+
953
+ final_offset = offset if offset is not None and not has_individual else (
954
+ individual_offset if has_individual else None
955
+ )
956
+
902
957
  # Apply offset if provided
903
- if offset is not None:
904
- if len(offset) != 6:
958
+ if final_offset is not None:
959
+ if len(final_offset) != 6:
905
960
  raise PointError(
906
961
  f"Offset must have 6 values [dx, dy, dz, drx, dry, drz], "
907
- f"got {len(offset)}."
962
+ f"got {len(final_offset)}."
908
963
  )
909
- point = point.with_offset(offset, frame=frame or self._move_frame)
964
+ point = point.with_offset(final_offset, frame=frame or self._move_frame)
910
965
 
911
966
  pose = list(point.pose)
912
967
 
@@ -978,12 +1033,18 @@ class URRobot:
978
1033
 
979
1034
  def move_relative(
980
1035
  self,
981
- delta: list[float],
1036
+ delta: list[float] | None = None,
982
1037
  *,
983
1038
  linear: bool = True,
984
1039
  frame: MoveFrame | None = None,
985
1040
  vel: float | None = None,
986
1041
  acc: float | None = None,
1042
+ delta_x: float = 0.0,
1043
+ delta_y: float = 0.0,
1044
+ delta_z: float = 0.0,
1045
+ delta_rx: float = 0.0,
1046
+ delta_ry: float = 0.0,
1047
+ delta_rz: float = 0.0,
987
1048
  ) -> None:
988
1049
  """Relative Cartesian move from the current position.
989
1050
 
@@ -992,27 +1053,55 @@ class URRobot:
992
1053
 
993
1054
  Args:
994
1055
  delta: [dx, dy, dz, drx, dry, drz] in meters/radians.
1056
+ Mutually exclusive with individual delta_* parameters.
995
1057
  linear: If True (default), use Cartesian linear move.
996
1058
  If False, solve IK and use joint-space move.
997
1059
  frame: Coordinate frame for the delta. Falls back to the
998
1060
  current ``move_frame`` property (BASE or TOOL).
999
1061
  vel: Velocity override. Falls back to default_vel.
1000
1062
  acc: Acceleration override. Falls back to default_acc.
1063
+ delta_x: X delta in meters (default 0.0).
1064
+ delta_y: Y delta in meters (default 0.0).
1065
+ delta_z: Z delta in meters (default 0.0).
1066
+ delta_rx: Roll delta in radians (default 0.0).
1067
+ delta_ry: Pitch delta in radians (default 0.0).
1068
+ delta_rz: Yaw delta in radians (default 0.0).
1001
1069
 
1002
1070
  Raises:
1003
1071
  MotionError: If the move fails.
1004
1072
 
1005
1073
  Example:
1006
- >>> robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
1007
- >>> robot.move_relative([0, 0, 0.05], frame=MoveFrame.TOOL)
1074
+ >>> robot.move_relative(delta_y=0.01) # 1cm along Y
1075
+ >>> robot.move_relative(delta_z=0.05, frame=MoveFrame.TOOL)
1076
+ >>> robot.move_relative([0, 0.01, 0, 0, 0, 0]) # full list
1008
1077
  """
1009
1078
  self._check_connection()
1010
1079
  self._disable_freedrive_guard()
1011
1080
 
1012
- if len(delta) != 6:
1081
+ # Build delta from individual params or use provided list
1082
+ individual_delta = [delta_x, delta_y, delta_z, delta_rx, delta_ry, delta_rz]
1083
+ has_individual = any(v != 0.0 for v in individual_delta)
1084
+
1085
+ if delta is not None and has_individual:
1086
+ raise MotionError(
1087
+ "Cannot use both 'delta' list and individual delta_* parameters. "
1088
+ "Use one or the other."
1089
+ )
1090
+
1091
+ final_delta = delta if delta is not None and not has_individual else (
1092
+ individual_delta if has_individual else None
1093
+ )
1094
+
1095
+ if final_delta is None:
1096
+ raise MotionError(
1097
+ "Relative move requires either 'delta' list or at least one "
1098
+ "delta_* parameter."
1099
+ )
1100
+
1101
+ if len(final_delta) != 6:
1013
1102
  raise MotionError(
1014
1103
  f"Relative move requires 6 values [dx,dy,dz,drx,dry,drz], "
1015
- f"got {len(delta)}."
1104
+ f"got {len(final_delta)}."
1016
1105
  )
1017
1106
 
1018
1107
  vel = vel if vel is not None else self._default_vel
@@ -1021,7 +1110,7 @@ class URRobot:
1021
1110
 
1022
1111
  try:
1023
1112
  current = list(self._rtde_r.getActualTCPPose())
1024
- target = transform_pose_delta(current, delta, effective_frame)
1113
+ target = transform_pose_delta(current, final_delta, effective_frame)
1025
1114
 
1026
1115
  if linear:
1027
1116
  self._motion.movel(target, vel=vel, acc=acc)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.7
3
+ Version: 0.3.8
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -88,7 +88,7 @@ robot = URRobot(ip="192.168.1.50", points="points.db", gripper=ROBOTIQ_HAND_E)
88
88
  robot.gripper.activate()
89
89
 
90
90
  robot.move_to("home")
91
- robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0])
91
+ robot.move_to("pick", offset_z=0.05) # 5cm above
92
92
  robot.gripper.close()
93
93
  robot.move_to("place")
94
94
  robot.gripper.open()
@@ -394,10 +394,12 @@ A pose is `[x, y, z, rx, ry, rz]`: position in meters and orientation as a **rot
394
394
 
395
395
  #### Offsets
396
396
 
397
- Offsets are 6-element lists `[dx, dy, dz, drx, dry, drz]`:
397
+ Offsets can use individual parameters or a full 6-element list:
398
398
 
399
399
  ```python
400
- robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0]) # 5cm above pick
400
+ robot.move_to("pick", offset_z=0.05) # 5cm above
401
+ robot.move_to("pick", offset_x=0.01, offset_z=-0.02) # combined
402
+ robot.move_to("pick", offset=[0, 0, 0.05, 0, 0.1, 0]) # full with rotation
401
403
  ```
402
404
 
403
405
  #### Resolve a Pose
@@ -416,7 +418,7 @@ robot.move_to(pose) # move to the resolved pose later
416
418
  from urkit import MoveFrame
417
419
 
418
420
  robot.move_frame = MoveFrame.TOOL # default is BASE
419
- robot.move_relative([0, 0, 0.05, 0, 0, 0]) # 5cm along tool Z
421
+ robot.move_relative(delta_z=0.05) # 5cm along tool Z
420
422
  ```
421
423
 
422
424
  - **BASE** (default): delta relative to robot base
@@ -440,8 +442,9 @@ robot.import_points("backup.json")
440
442
  #### Relative Moves
441
443
 
442
444
  ```python
443
- robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
444
- robot.move_relative([0, 0, 0.05, 0, 0, 0], frame=MoveFrame.TOOL) # 5cm along tool Z
445
+ robot.move_relative(delta_y=0.01) # 1cm along Y
446
+ robot.move_relative(delta_z=0.05, frame=MoveFrame.TOOL) # 5cm along tool Z
447
+ robot.move_relative([0, 0.01, 0, 0, 0, 0])
445
448
  ```
446
449
 
447
450
  #### Sequences with Blending
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes