Bu bölümün laboratuvarı, kitaptaki örnekleri yeniden üretmek ve sayısal sonuçları incelemek için hazırlanmıştır. Matematiksel tanımlar, ispatlar ve sorular kitapta yer alır.
Laboratuvar kodu
"""Bölüm 7 laboratuvarı: yerel CAD çerçevesinden robot dünyasına geçiş.
Model iki boyutlu ve sentetiktir. Koordinatlar milimetre, açılar sunumda
derecedir. Üç boyutlu poz, mekanik tolerans, kamera modeli, çarpışma ve
güvenlik denetimi içermez.
"""
from __future__ import annotations
import numpy as np
from agbook import (
canonical_array_sha256,
compose_rigid_motions,
coordinates_from_frame,
coordinates_in_frame,
inverse_rigid_motion,
line_from_points,
pairwise_distances,
polygon_signed_area,
reflect_across_line,
rigid_motion_diagnostics,
rigid_transform,
rotation_matrix_2d,
)
def main() -> None:
part_local = np.array(
[[0.0, 0.0], [120.0, 0.0], [120.0, 60.0], [0.0, 60.0]]
) # mm
feature_local = np.array([95.0, 45.0]) # mm
frame_origin = np.array([420.0, 180.0]) # mm, dünya çerçevesinde
frame_angle_deg = 35.0
frame_axes = rotation_matrix_2d(np.deg2rad(frame_angle_deg))
part_world = coordinates_from_frame(part_local, frame_origin, frame_axes)
feature_world = coordinates_from_frame(feature_local, frame_origin, frame_axes)
recovered_local = coordinates_in_frame(part_world, frame_origin, frame_axes)
frame_diagnostics = rigid_motion_diagnostics(
part_local,
frame_axes,
frame_origin,
)
local_datum = np.array([0.0, 1.0, -30.0]) # y=30 mm
reflected_local = reflect_across_line(feature_local, local_datum)
reflected_world_from_local = coordinates_from_frame(
reflected_local,
frame_origin,
frame_axes,
)
datum_world_points = coordinates_from_frame(
[[0.0, 30.0], [120.0, 30.0]],
frame_origin,
frame_axes,
)
datum_world = line_from_points(datum_world_points[0], datum_world_points[1])
reflected_world_direct = reflect_across_line(feature_world, datum_world)
sensor_rotation = rotation_matrix_2d(np.deg2rad(-12.0))
sensor_origin_in_part = np.array([35.0, 20.0]) # mm
sensor_shape = np.array([[0.0, 0.0], [24.0, 0.0], [12.0, 10.0]]) # mm
composed = compose_rigid_motions(
frame_axes,
frame_origin,
sensor_rotation,
sensor_origin_in_part,
)
sensor_world_direct = rigid_transform(
sensor_shape,
composed.matrix,
composed.translation,
)
sensor_world_sequential = coordinates_from_frame(
rigid_transform(sensor_shape, sensor_rotation, sensor_origin_in_part),
frame_origin,
frame_axes,
)
inverse = inverse_rigid_motion(composed.matrix, composed.translation)
sensor_recovered = rigid_transform(
sensor_world_direct,
inverse.matrix,
inverse.translation,
)
print("birim: mm")
print("cerceve_acisi_derece:", f"{frame_angle_deg:.1f}")
print("cerceve_baslangici:", np.round(frame_origin, 9))
print("cerceve_determinanti:", f"{np.linalg.det(frame_axes):.12f}")
print("ortogonallik_artigi:", f"{frame_diagnostics.orthogonality_residual:.3e}")
print("yerel_ozellik:", np.round(feature_local, 9))
print("dunya_ozellik:", np.round(feature_world, 9))
print("cerceve_gidis_donus_artigi_mm:", f"{np.max(np.abs(recovered_local - part_local)):.3e}")
print("uzaklik_artigi_mm:", f"{np.max(np.abs(pairwise_distances(part_world) - pairwise_distances(part_local))):.3e}")
print("yerel_yonlu_alan_mm2:", f"{polygon_signed_area(part_local):.6f}")
print("dunya_yonlu_alan_mm2:", f"{polygon_signed_area(part_world):.6f}")
print("yansitilmis_yerel_ozellik:", np.round(reflected_local, 9))
print("yansima_cerceve_uyumu_mm:", f"{np.max(np.abs(reflected_world_direct - reflected_world_from_local)):.3e}")
print("bilesik_determinant:", f"{composed.determinant:.12f}")
print("bilesim_artigi_mm:", f"{np.max(np.abs(sensor_world_direct - sensor_world_sequential)):.3e}")
print("ters_hareket_artigi_mm:", f"{np.max(np.abs(sensor_recovered - sensor_shape)):.3e}")
signature_values = np.concatenate(
[
part_world.ravel(),
feature_world,
reflected_world_direct,
composed.matrix.ravel(),
composed.translation,
]
)
print("bilimsel_imza:", canonical_array_sha256(signature_values))
if __name__ == "__main__":
main()
Doğrulama çalıştırmasının çıktısı
birim: mm
cerceve_acisi_derece: 35.0
cerceve_baslangici: [420. 180.]
cerceve_determinanti: 1.000000000000
ortogonallik_artigi: 1.570e-16
yerel_ozellik: [95. 45.]
dunya_ozellik: [472.00850457 271.35160345]
cerceve_gidis_donus_artigi_mm: 5.684e-14
uzaklik_artigi_mm: 5.684e-14
yerel_yonlu_alan_mm2: 7200.000000
dunya_yonlu_alan_mm2: 7200.000000
yansitilmis_yerel_ozellik: [95. 15.]
yansima_cerceve_uyumu_mm: 5.684e-14
bilesik_determinant: 1.000000000000
bilesim_artigi_mm: 2.842e-14
ters_hareket_artigi_mm: 5.684e-14
bilimsel_imza: f9569f7376364a0d502180e57b2a5184658a08fe3c698061f8f5bc8277a74062
Metindeki Python kodları
# Kitaptaki kod blokları; bu dosya içinde sırayla çalıştırılır.
# --- 1. Bölüm 7: yerel CAD çerçevesinden dünyaya geçiş ---
import numpy as np
from agbook import (
coordinates_from_frame,
coordinates_in_frame,
pairwise_distances,
polygon_signed_area,
reflect_across_line,
rigid_motion_diagnostics,
rotation_matrix_2d,
)
part_local = np.array([
[0.0, 0.0], [120.0, 0.0],
[120.0, 60.0], [0.0, 60.0],
]) # mm
feature_local = np.array([95.0, 45.0]) # mm
origin = np.array([420.0, 180.0]) # mm
axes = rotation_matrix_2d(np.deg2rad(35.0))
part_world = coordinates_from_frame(part_local, origin, axes)
feature_world = coordinates_from_frame(feature_local, origin, axes)
recovered = coordinates_in_frame(part_world, origin, axes)
diagnostics = rigid_motion_diagnostics(part_local, axes, origin)
reflected = reflect_across_line(feature_local, [0.0, 1.0, -30.0])
distance_residual = np.max(np.abs(
pairwise_distances(part_world) - pairwise_distances(part_local)
))
print("dunya_ozellik:", np.round(feature_world, 8))
print("yansitilmis_yerel_ozellik:", reflected)
print("ortogonallik_artigi:", f"{diagnostics.orthogonality_residual:.3e}")
print("gidis_donus_artigi_mm:", f"{np.max(np.abs(recovered-part_local)):.3e}")
print("uzaklik_artigi_mm:", f"{distance_residual:.3e}")
print("alanlar_mm2:", polygon_signed_area(part_local),
polygon_signed_area(part_world))
Kaydedilen çıktı
1. Bölüm 7: yerel CAD çerçevesinden dünyaya geçiş
dunya_ozellik: [472.00850457 271.35160345]
yansitilmis_yerel_ozellik: [95. 15.]
ortogonallik_artigi: 1.570e-16
gidis_donus_artigi_mm: 5.684e-14
uzaklik_artigi_mm: 5.684e-14
alanlar_mm2: 7200.0 7199.999999999996
Çözümlerdeki Python kodları
# Kitaptaki kod blokları; bu dosya içinde sırayla çalıştırılır.
# --- 1. Dört noktanın yansıma koşullarını sınama ---
import numpy as np
from agbook import canonical_line_coefficients, reflect_across_line
points = np.array([[0., 0.], [2., -1.], [4., 3.], [-2., 5.]])
line = canonical_line_coefficients([2., -1., 3.])
images = reflect_across_line(points, line)
midpoints = 0.5 * (points + images)
tangent = np.array([-line[1], line[0]])
line_residuals = midpoints @ line[:2] + line[2]
perpendicularity = (images - points) @ tangent
print(np.max(np.abs(line_residuals)))
print(np.max(np.abs(perpendicularity)))
assert np.allclose(line_residuals, 0.0, atol=1e-12, rtol=0.0)
assert np.allclose(perpendicularity, 0.0, atol=1e-12, rtol=0.0)
# --- 2. Ardışık ve birleşik rijit hareket ---
import numpy as np
from agbook import (
compose_rigid_motions, rigid_transform, rotation_matrix_2d,
)
points = np.array([[0., 0.], [2., 1.], [-1., 3.]])
q1, t1 = rotation_matrix_2d(0.4), np.array([2., -1.])
q2, t2 = np.diag([1., -1.]), np.array([-3., 4.])
sequential = rigid_transform(rigid_transform(points, q1, t1), q2, t2)
motion = compose_rigid_motions(q2, t2, q1, t1)
direct = rigid_transform(points, motion.matrix, motion.translation)
print("bilesim_artigi:", np.max(np.abs(direct - sequential)))
print("ortogonallik_artigi:",
np.linalg.norm(motion.matrix.T @ motion.matrix - np.eye(2)))
print("determinant:", motion.determinant)
assert np.allclose(direct, sequential, atol=1e-12, rtol=0.0)
# --- 3. Çerçeve gidiş-dönüş ve uzaklık denetimi ---
import numpy as np
from agbook import (
coordinates_from_frame, coordinates_in_frame,
pairwise_distances, rotation_matrix_2d,
)
local = np.array([[0., 0.], [2., 0.], [2., 3.], [-1., 4.], [5., -2.]])
origin = np.array([100., -40.])
axes = rotation_matrix_2d(np.deg2rad(27.0))
world = coordinates_from_frame(local, origin, axes)
recovered = coordinates_in_frame(world, origin, axes)
roundtrip = np.max(np.abs(recovered - local))
distance = np.max(np.abs(
pairwise_distances(world) - pairwise_distances(local)
))
print(roundtrip, distance)
assert roundtrip <= 1e-12
assert distance <= 1e-12
# --- 4. Geçersiz eksen ve çerçeve testleri ---
import numpy as np
import pytest
from agbook import coordinates_from_frame, reflection_matrix_2d
with pytest.raises(ValueError, match="Yansıma ekseni"):
reflection_matrix_2d([0.0, 0.0])
non_orthonormal = np.array([[1.0, 0.4], [0.0, 1.0]])
with pytest.raises(ValueError, match="ortogonal"):
coordinates_from_frame([2.0, 3.0], [0.0, 0.0], non_orthonormal)
Kaydedilen çıktı
1. Dört noktanın yansıma koşullarını sınama
6.661338147750939e-16
4.440892098500626e-16
2. Ardışık ve birleşik rijit hareket
bilesim_artigi: 2.220446049250313e-16
ortogonallik_artigi: 3.0102202242079384e-17
determinant: -1.0
3. Çerçeve gidiş-dönüş ve uzaklık denetimi
1.4210854715202004e-14 8.43769498715119e-15
4. Geçersiz eksen ve çerçeve testleri
Çalıştırma rehberi
Önce tam Python paketini indirin ve arşivi açın. Aşağıdaki komutları arşivin üst klasöründen başlatın. İlk kurulum internet bağlantısı ve Python 3.12 veya 3.13 gerektirir. Bağımlılıklar sabittir; sistem Python'unu değiştirmemek için ayrı sanal ortam kullanılır.
macOS / Linux
cd analitik-geometri-python-v1.0
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
python labs/bolum_07_oteleme_donme_yansima.py
python -m pytestWindows PowerShell
cd analitik-geometri-python-v1.0
py -3.13 -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
.venv\Scripts\python.exe labs/bolum_07_oteleme_donme_yansima.py
.venv\Scripts\python.exe -m pytest