Software Engineer — Perception, Embedded AI & Full-Stack Systems
I work on measurement, and on what depends on it.
I work where the method only exists on paper — designing the approach, building the hardware and signal chain it needs, and getting it to hold up on real data outside the lab.
Six cases are on this site. Every one of them carries the number it was actually measured at, together with the condition it was measured under — including the case where the honest number came out far worse than the first one I got, and became the finding instead of a footnote.
The shape of the work. The trace is a synthetic channel; the step curve under it is not decoration, it is that same trace reduced to one value per window, computed at build time. A noisy input on top, a number you can defend underneath, and the condition written next to it. Schematic, generated deterministically at build time; not a measurement.
Scene 02 — How I work
Where the method only exists on paper
I work on making sensors trustworthy — detecting when a LiDAR is being lied to, and hearing what a plant cannot say.
The work usually starts before there is anything to build. A defence exists in the literature but collapses in exactly the condition that matters. A measurement is established science but lives on instrumentation costing thousands of euros. A privacy rule everyone agrees on survives until the first person forgets it. In each case the interesting part is not writing the code — it is deciding where the guarantee should live so that it holds without anyone having to remember it.
That place is usually one layer lower than expected. A rule about who may see a reporter's identity belongs in the type system and in the database, not in a comment. Tenant isolation belongs in Row-Level Security, not in 142 endpoints. A job queue on a server with no GPU belongs in the database that is already running, not in a message broker nobody wanted to operate. And a detector's accuracy belongs to the data it was measured on, not to the simulator it was trained in.
The rest is ordinary and I do it properly. Two internships at Beyond Technologies in Ankara put me on real vehicles: ROS2 perception for unmanned ground vehicles — LiDAR/camera fusion, Cylinder3D on WildScenes, real-time inference on Jetson Orin Nano. Invited back with independent ownership of the perception stack. Deployments run through smoke tests with automatic rollback, and there are enough tests that a change on a Friday is not an event. I also teach: at Hello World in Adana I am community co-lead and instructor — 20+ hands-on workshops in Java, Python and web development, reaching over 300 students.
Useful for
three lanes
Perception and signals
ROS2, LiDAR and camera fusion, 3D point cloud segmentation, FFT and STFT, CFAR thresholding, embedded acoustic sensing.
Production backends
NestJS and TypeScript over PostgreSQL, with isolation and audit enforced in the database — RLS, PostGIS, pgvector, and Neo4j where the data is genuinely a graph.
Embedded and hardware
Custom analogue circuits, RP2040 and Jetson Orin Nano, real-time inference inside a fixed frame budget.
One claim and one figure each. The signature strip under every entry is drawn from that project's own domain — a range profile, a report's route, a security boundary, an audiogram, a job queue, an acoustic raster. All of them are schematics generated at build time, never captures.
Detecting LiDAR spoofing from a single frame, while the vehicle is standing still.
Grey is the authentic surface profile. The flat magenta segment is an injected return sitting closer than any real surface in that direction, and the faint dotted line beneath it is the surface it hides. Because it holds still across frames, the standard frame-to-frame defence subtracts it away along with everything else. Schematic, generated deterministically at build time; not a capture.
Hearing a plant run out of water, on under €10 of hardware.
A plant short of water pulls harder on the water in its conducting tissue. Occasionally one of those columns breaks, and the break makes a sound far above human hearing. The device counts those clicks. That is established science, but it lived in laboratories on instrumentation costing thousands of euros; this reproduces it on under 10 euros, with a custom piezo circuit on a Raspberry Pi Pico W and FFT separating the plant signal from ambient noise. The hour drawn here uses the measured rates — the tick times are synthetic, the rates are the result.
142 endpoints, and not one of them is responsible for keeping the schools apart.
Every request runs inside a single transaction with its school's context set, under RLS policies; with no context, no row is visible at all, and the super-admin surface runs as a separate database role. This is client work, so the figures are scale and architecture only — 28 tables, four user roles, Argon2id with TOTP, and around 420 automated tests across four layers. Schematic of the mechanism, not measured data.
Two databases, because clinical reasoning is a graph and patient identity is not.
Patient identity is relational and rigid, so it lives in PostgreSQL. Clinical reasoning — visits, diagnoses, diseases, devices and the similarity between patients — is a network, so it lives in Neo4j and is navigated with weighted traversal for differential diagnosis. Patient data is encrypted with AES-256-GCM, and the audit log is hash-chained and append-only, enforced by a database trigger the application layer cannot bypass. The thresholds drawn here are synthetic: no patient data, no screenshots, no client names.
40+ centres · PostgreSQL and Neo4j · KVKK and ISO 27001Read the Vera case
A privacy rule the compiler enforces, not the code review.
Neighbours never see who filed a report; the institution does. That rule is not a comment — citizen-facing and institution-facing queries live in repository classes that cannot reach each other at compile time, tenant isolation runs on PostgreSQL Row-Level Security with the connection pinned per request, and an end-to-end regression test guards the boundary. No national ID number and no phone number is ever requested, and there is no super-user and no reputation score. Schematic of the method, not measured data.
No GPU on the server and no message broker in the stack — PostgreSQL is the queue.
The server has no GPU, so inference runs on a local Python worker driving Qwen through Ollama and polling over HTTP. Rather than add Redis or RabbitMQ, the queue is one ai_jobs table: a partial index over pending rows ordered by creation time, and an atomic claim that stops two workers taking the same job. Fewer moving parts, less to operate, one less thing that can be down. Schematic of the mechanism, not measured data.
12+ cognitive metrics · PostgreSQL and MongoDB · offline-firstRead the LQ case
A figure without its condition is decoration. Each of these carries the condition it holds under, and where something was never measured, the case page says so rather than reaching for a number.
81.6%
SHIELD accuracy on real sensor captures
38.8ms
per frame — inside a 10 Hz LiDAR budget
69×
event-rate margin, stressed vs. healthy plant
300+
students taught across 20+ workshops
142endpoints
Limon Akademi — and not one of them keeps the schools apart
76tests
Şeffaf Şehir — run against a real PostGIS instance in CI
On the first number I got
SHIELD scored 97.1% in simulation and 8.2% on data from a real sensor, with more than nine out of ten alarms false. There was an easy way out of that: keep training on synthetic data, report the simulation figure, and put the real-world result in a footnote. Instead the collapse became the finding, and the work turned into locating exactly where the gap between the two worlds lives.
The fix was to move the attacks rather than the data — synthetic spoofing signatures injected onto authentic recordings at the trace level, so the noise floor, the dropouts and the reflectivity behaviour stay exactly as the sensor recorded them while the ground truth stays exact. That brought accuracy back to 79.3%, and the full pipeline to 81.6%. It is a smaller number than the one I started with, and it is the one I can defend.
Same model
simulation vs. real
Simulation only97.1%
Real sensor data8.2%
Final system, authentic captures81.6%
Unchanged model, changed data. The first bar is the reason the third one is worth reporting at all.
Scene 05 — Contact
Two kinds of message are welcome
I work on measurement, and on what depends on it.Ali Batuhan Özsürmeli
If you are hiring for perception, signal processing, or a backend where the security guarantees have to hold without anyone remembering them, the six cases above are the evidence, and every figure on them has its conditions attached.
If you have a project to build, the useful first message is the constraint rather than the feature list — what has to be true, what the budget is, and what happens if it turns out to be wrong. That is the part that decides the architecture, and it is the part I want to hear first.