今日已更新 143 条资讯 | 累计 40588 条内容
关于我们

标签:#python

找到 1205 篇相关文章

AI 资讯

Atomic writes — how tempfile + os.replace prevent corrupted JSON

What happens if the power cuts out while a process is writing to a config file? Or if antivirus software on Windows briefly locks a file mid-write? If you naively overwrite a file with open(path, 'w') , whatever partial content existed at the moment of interruption is what remains on disk. For JSON, that usually means broken syntax — json.load() throws on the next startup, and the entire configuration is effectively lost. This article walks through a standard technique for preventing that: writing to a temporary file first, then swapping it in atomically. Note: "Atomic" here means an operation either completes entirely or doesn't happen at all — there's no partial, observable in-between state. It's the same sense of the word used for database transactions. Why direct overwrites are dangerous open(path, 'w') effectively truncates the file first and then writes the new content. If the process is interrupted during that window, the file is left empty or holding incomplete content. # Dangerous: a crash mid-write leaves a corrupted file behind with open ( ' config.json ' , ' w ' ) as f : json . dump ( data , f ) # what if this gets interrupted? The causes vary: a kill -9 , a power outage, antivirus software briefly blocking file access on Windows, or a backup tool grabbing the file mid-write. This rarely reproduces during local development, but in a long-running production environment, it will eventually happen with near certainty. The fix: write to a temp file, then swap it in The core idea is simple. Never touch the target file directly. Write the complete new content to a temporary file first, confirm that write fully succeeded, and only then replace the target file with that temp file. import json import os import tempfile def atomic_write_json ( filepath , data ): dirpath = os . path . dirname ( os . path . abspath ( filepath )) or ' . ' fd , tmp_path = tempfile . mkstemp ( dir = dirpath , suffix = ' .json.tmp ' ) try : with os . fdopen ( fd , ' w ' , encoding = ' u

2026-09-08 原文 →
AI 资讯

Your system prompt isn't instructions. It's data.

My system prompt had an example of a good Slack message in it. It opened with "Morning all, quick one:". The model started opening real Slack drafts with that exact phrase. Then it started saying "Morning." when I typed "hey", which is a small lie, because it cannot see a clock. So I added a rule telling it not to reuse examples from its own instructions. Three rebuilds. No change. Then I deleted the phrase. Fixed on the next build. That is when it clicked. The model does not read your system prompt as a list of instructions. It reads it as text that is likely to appear near its own output. Every finding below falls out of that one idea. The four rules I now write prompts by If a phrase must not appear in the output, it must not appear in the prompt. Banning it does not work. Deleting it does. Naming a bad example summons it. "Not the bank balance one" is an excellent way to get the bank balance one. Position beats wording. A rule buried mid-section gets read and traded away. The same words at the top of that section hold. Concrete beats principled. "Call fsync() before the rename" lands immediately. "Describe only the guarantee the code actually makes" does nothing. And the one that saved me the most time after it cost me the most time: verify on three seeds before you believe any of it. Here is the evidence for each. The setup Flash Onyx is the model line behind Flash , my local agent shell. There is no fine-tuning involved. Onyx is a base model plus a system prompt that has grown to roughly 680 lines, built into an Ollama tag with a small script: python3 models/build.py models/flash-onyx-2.5.Modelfile --size 31b-cloudbase -n Natuworkguy 2.5 is the version where I stopped editing that prompt by feel. The loop is not clever: edit the prompt, rebuild the tag, run a fixed set of prompts at pinned seeds, read the output, decide whether anything actually changed. Seeds are pinned so two runs are comparable. That is the entire method, and it is the difference between "t

2026-09-08 原文 →
AI 资讯

Your text-to-SQL agent picks tables before security runs. Here’s the fix.

I build text-to-SQL agents on Oracle and Postgres for a living. Every one of them had the same bug, and it wasn’t in my code. It was in the order of operations. The bug The schema goes into the prompt before the query runs. Row-level security runs when the query runs. So the model sees a table the user can’t read, writes perfectly valid SQL against it, the database returns zero rows, and the agent says “no records found”. A wrong answer, delivered with confidence. Vanna (23k stars, archived March 2026) applied identity exactly there: at execution, after the model had seen everything. The fix Apply identity at selection. Decide which tables the model is shown, per caller, before any SQL exists. A restricted table isn’t ranked low — it’s absent. from schemagate import Catalog, Principal cat = Catalog().bootstrap("postgresql://localhost/app") cat.restrict("hr_compensation", roles=["payroll"]) analyst = Principal("okta:jdoe", roles={"analyst"}) cat.select("salary by employee", principal=analyst).table_names # no hr_compensation pip install schemagate — one dependency, no API key, any SQLAlchemy database. The side effect that pays for it You’re now sending ~6 tables instead of the schema dump. Measured on the test schemas: 65–79% fewer prompt tokens on small ones, 97% on a 260-object one (16,095 → 444 per question). The selector never calls a model — BM25 plus a hashed embedder, offline, milliseconds. What broke while building it Six invented schemas found ten bugs before release. My favourite: a three-column orders_bkp outranked the real orders table, because short documents win cosine similarity. Backup and staging copies now rank below the object they shadow. The full list is in TESTING.md. Where it plugs in MCP server for Claude Desktop and Cursor, a LangChain retriever, a native Oracle 23ai VECTOR store, and a browser demo that needs no install: https://ashishsinha1602.github.io/schemagate/ Repo: https://github.com/ashishsinha1602/schemagate — tell me where it break

2026-09-08 原文 →
AI 资讯

Stopwatch First: Local Work or a Remote Hop

Guessing local versus remote wastes both battery and tokens. Measure three gates before any prompt leaves disk. Connectivity, secret residue, and wall-clock cost decide the hop. A laptop is a workshop on your desk. A remote model is a mill across town. You do not crate the shop for one cut. House keys do not travel with the lumber. Secrets inside a prompt are those house keys. A free mill still sits far across town. This article is a measurement workflow, not a bake-off. The script below is a labeled example only. Run it locally and trust only its clocks. Coding agents now plan, search, and generate together. Local context is cheap to read from disk. Completion on a cold CPU can stall hard. Remote completion can still win on that stall. It can also leak residue or hang offline. Extra latency can erase the time it saves. Weekly agent glossaries rename the same moving parts. The useful question stays narrower than weekly branding. When does a remote hop beat a local stall? Three gates before the mill Three gates answer that without slogans or dashboards. Gate one is reachability on the open wire. Gate two is leftover secret material in text. Gate three is a stopwatch on both sides. Skip any gate and the decision is folklore. Folklore is how keys leave working laptops daily. The wire is a hard constraint, not a preference. If the socket fails, stay on local disk. Offline work does not negotiate with a mill. Secret residue is the second hard stop today. Clean the text or refuse the send. A price of zero does not change that physics. Only then time the work with a cheap stub. Walk the tokens on CPU and probe RTT. Remote wins when CPU dominates a thin payload. Arithmetic beats instinct on that last gate check. A long round trip cannot beat a short stub. A throttled laptop can still lose on decode. Do not assume which machine is slower today. Thermal state and queue time both move around. Measure the hop on the machine you have. Disclosure: This article was prepared as par

2026-09-07 原文 →
AI 资讯

Inside vLLM: Following One Request from the API to GPU Execution

Article 1 of 3 · vLLM Internals This English edition is adapted from the published Chinese article on Zhihu . It preserves the source-code references, experimental boundaries, and reproducible artifacts while adapting the structure for an international engineering audience. Series: Part 1 · Request lifecycle · Part 2 · CUDA kernels and paged attention · Part 3 · FlashAttention from PyTorch to Triton This article follows one offline inference request through vLLM V1: from LLM.generate() and inter-process communication to scheduling, input flattening, GPU model execution, paged KV-cache access, sampling, and resource reclamation. The goal is to answer one concrete question: what happens behind the call to llm.generate() before the completed result reaches the caller? The discussion assumes familiarity with Transformer inference, including prefill, decode, KV caching, and autoregressive generation. It focuses on how those concepts appear in vLLM source code rather than reteaching the model architecture. Version scope. The source references were verified against vLLM 0.22.0; this edition was checked on September 3, 2026. vLLM evolves quickly, so some filenames and call boundaries will move. The long-lived ideas—continuous batching, token budgets, paged KV allocation, and the separation between scheduling and execution—are the real subject of the article. Why Read the Source Instead of Another API Guide? Many introductions stop at the useful analogy that PagedAttention manages the KV cache much like virtual memory manages pages. The analogy does not tell us how a request is admitted, how variable-length requests become a flat token batch, or what the page table looks like at the kernel boundary. The answers are in the source. This article follows vLLM 0.22's V1 execution path from the public entry point to the CUDA boundary. It is a source-code walkthrough, not an API tutorial. Start with a System Map Start with the process boundary and the engine loop. In vLLM V1, Engin

2026-09-07 原文 →
AI 资讯

Beyond the Wrist: Detecting Sickness Before It Hits with HRV Anomaly Detection and Scikit-learn

Ever woke up feeling like a truck hit you, only to realize your Apple Watch had been screaming "Warning!" via your data for the last 24 hours? Heart Rate Variability (HRV) is the "canary in the coal mine" for our bodies. It's a powerful metric that tracks the variation in time between each heartbeat, serving as a direct window into your Autonomic Nervous System. In this guide, we are going to build a real-time HRV anomaly detector using wearable data analysis , Scikit-learn , and AWS Lambda . By applying machine learning to time-series health data, we can identify physiological stress, potential infections, or overtraining before physical symptoms even manifest. If you’ve been looking to dive into anomaly detection in time-series or want to master health data engineering , you’re in the right place! The Architecture: From Heartbeat to Alert 🛠️ To achieve real-time monitoring, we need a pipeline that moves data from your wrist to a cloud-based inference engine. Here is the high-level flow: graph TD A[Apple Watch / Wearable] -->|Sync| B(Apple HealthKit) B -->|Webhook/Hook| C[AWS API Gateway] C --> D[AWS Lambda - Inference] D -->|Fetch History| E[(DynamoDB / S3)] D -->|Isolation Forest| F{Anomaly?} F -->|Yes| G[Push Notification / Alert] F -->|No| H[Log & Silent] Prerequisites 📋 Before we start coding, ensure you have the following: Python 3.9+ Scikit-learn & Pandas for data crunching. AWS Account (for Lambda deployment). An app to push HealthKit data (like Health Auto Export or a custom Swift hook). Step 1: Understanding the Data 📊 HRV data is tricky because it’s highly personalized. What is "low" for an athlete might be "high" for someone else. This is why we use Isolation Forest , an unsupervised learning algorithm that excels at detecting outliers in multi-dimensional datasets without needing labeled "sick" vs. "healthy" days. Step 2: Building the Anomaly Detection Logic Let's write the core logic using Scikit-learn . We’ll use the Isolation Forest algorithm becaus

2026-09-07 原文 →
AI 资讯

Local Embeddings vs. API Embeddings — Why I Chose sentence-transformers

Every RAG pipeline needs to convert text into vectors. The question is where that conversion happens. You have two options: run an embedding model locally on your own hardware, or call an API that runs the model on someone else's hardware. Both work. The right choice depends on your constraints — and understanding the tradeoffs is more useful than a recommendation. This article is about why I chose local embeddings with sentence-transformers/all-MiniLM-L6-v2 for this pipeline, and when I'd switch to an API. What Embeddings Actually Do Before the tradeoffs, a quick grounding on what's happening. An embedding model takes text and converts it into a fixed-size vector of floating-point numbers — a list of 384 numbers in the case of all-MiniLM-L6-v2 . That vector encodes the semantic meaning of the text in a way that allows mathematical comparison. Two pieces of text with similar meaning produce vectors that are close together in the 384-dimensional vector space. "Authentication failed" and "login was rejected" are semantically similar — their vectors will be close. "Authentication failed" and "quarterly revenue report" are semantically distant — their vectors will be far apart. This is what makes retrieval work. When you embed a query and search for the nearest chunks, you're finding chunks that are semantically similar to the question — not just chunks that contain the same keywords. The embedding model determines the quality of this semantic matching. A better model produces vectors where semantic similarity maps more accurately to vector proximity. The Local Embedding Choice My pipeline uses sentence-transformers/all-MiniLM-L6-v2 via ChromaDB's SentenceTransformerEmbeddingFunction : from chromadb.utils.embedding_functions import SentenceTransformerEmbeddingFunction embedding_fn = SentenceTransformerEmbeddingFunction ( model_name = " sentence-transformers/all-MiniLM-L6-v2 " ) This runs entirely on your local CPU. No API key, no network request, no cost per embedding,

2026-09-07 原文 →
AI 资讯

Why I Rewrote Four Services in Go

I had four small services. Each one was a Model Context Protocol adapter — a thin wrapper that lets an AI agent call out to some external thing. One talked to Replicate for image generation. One talked to a Nostr-friendly social poster. One was a Git-aware research helper. One was a Tavily-powered web search. They were all written in Python. They all ran on Knative on a small Kubernetes cluster. They all worked. And they were all just slightly too slow to use. A six-second cold start is fine for nothing. It is the precisely wrong amount of time — slow enough to be noticed, fast enough to feel almost loaded. An AI agent waiting six seconds for a single tool call does not know it is waiting for a cold start; it just knows the tool is sluggish. The user does not know either. The user just thinks the agent is broken. And six seconds was a good day. Some of the services took longer. So I rewrote them in Go. This is what that cost me, and what the measurements actually were before and after. The actual problem Cold starts on serverless platforms are an old problem with a well-known shape. The platform spins your container up only when traffic arrives, so the first request after an idle period pays the full startup tax — image pull (or warm cache hit), container start, language runtime initialisation, application bootstrap. For Python, application bootstrap is where the bill arrives. The interpreter has to start. import statements run. The dependency tree gets walked. If you have ever wondered why a hello world Flask app feels so much heavier than a hello world Go binary, this is why. Python is doing real work before your code runs. Go has already started. On a small Kubernetes cluster — small as in I am paying for it personally — you do not keep a fleet of warm replicas around. You scale-to-zero. You scale-to-zero because that is the entire point of using serverless on small infrastructure. The trade-off is that every idle service eats a cold start the next time it is inv

2026-09-06 原文 →
AI 资讯

Building a Real-Time Price Anomaly Detector with Python, SerpApi, and Robust Statistics

Modern price monitoring systems need to do more than tell you that a price changed. A single abnormal listing, a scraped error, or a temporary outlier can make a traditional threshold-based detector fire an alert when nothing meaningful happened. In this project, I built a lightweight real-time price anomaly detector in Python that combines: A rolling median baseline Median Absolute Deviation (MAD) Robust Z-scores Short-term percentage returns Trend confirmation Alert cooldowns The goal is simple: detect meaningful price movements without overreacting to noisy observations. Note: This project monitors retail prices from Google Shopping results through SerpApi. It is a retail-price monitoring example, not a financial exchange-data feed. What we're building The pipeline looks like this: ┌──────────────────────┐ │ SerpApi / Shopping │ └──────────┬───────────┘ │ ▼ ┌──────────────────┐ │ Price Extraction │ │ + Validation │ └────────┬─────────┘ │ ▼ ┌────────────────────┐ │ Rolling Price │ │ History │ └────────┬───────────┘ │ ┌───────────┼───────────┐ ▼ ▼ ▼ Median MAD Return % │ │ │ └───────────┼───────────┘ ▼ Robust Z-score │ ▼ Trend Confirmation │ ▼ Signal Engine │ ▼ Alert Cooldown The implementation is intentionally small and interpretable. The complete engine is built around a single PriceAlertEngine class and a compact AnomalyResult data structure. Why not just use standard deviation? A common first implementation is: price > mean + 3 * standard_deviation The problem is that standard deviation is sensitive to extreme observations. Suppose your historical prices are: 990, 995, 999, 1001, 1005 Then one bad observation such as: 1500 can distort the mean and standard deviation. That can move your detection boundary away from the actual market behavior you are trying to model. For a noisy retail environment, a more robust baseline is useful. That's where median and Median Absolute Deviation come in. 1. Building a rolling median baseline Instead of storing an unlimited stre

2026-09-06 原文 →
AI 资讯

trelix v3.2.2 to v3.2.5: The Source Tree Was Fine. The Published Package Wasn't.

Run this against the real, published image and watch it fail: docker run --rm --entrypoint trelix-mcp ghcr.io/sairam0424/trelix:3.2.1 --version Exit code 127. Not a crash inside trelix-mcp, not a stack trace, not a permissions error — 127 is the shell's own way of saying the binary you asked for does not exist. And it didn't. The console script trelix-mcp is supposed to install as part of every trelix package was simply absent from the image, on both the slim tag and the -local tag, for the entire life of the 3.2.1 release. Every unit test in the suite was green. Every line of source that builds trelix-mcp was correct. The thing a user would actually get from docker pull did not have the binary its own --version flag implies exists. This article covers four releases — v3.2.2, v3.2.3, v3.2.4, and v3.2.5 — spanning 173 commits and 88 changed files since v3.2.1, which is where the last article in this series left off. That one was about tests that pass without exercising the code they claim to cover: a MagicMock standing in for a real embedder, an all-ones attention mask that makes masked and unmasked math identical, a unit test that asserted a bug as its own specification. This one, on the heels of the mutation-testing push that closed out that arc, is about a different and in some ways more uncomfortable failure mode: tests that pass while exercising the wrong artifact entirely. A green pytest run against src/ says nothing about whether the wheel on PyPI, the image on GHCR, or the binary on the GitHub Releases page actually does what it claims. Those are three separate build products, built by three separate pipelines, and none of trelix's 4,353 collected unit tests had ever touched any of them directly. v3.2.2 through v3.2.4 is the story of finding that gap and closing it with an actual gate, not a promise to be more careful next time. v3.2.5 is a short postscript proving the discipline stuck. The Docker image that shipped without its own server The 127 above wasn't

2026-09-06 原文 →
AI 资讯

How to fetch the RBA cash rate in Python (without parsing CSVs)

If you have ever tried to programmatically get the current RBA cash rate, you know the drill. You open the RBA F1 statistical table, download f01hist.xls, write a pandas.read_excel call, fight with the multi-row header (Series ID on row 11, units on row 6), filter, sort, take the last row. That is 30 lines of code to get a single number that changes 11 times a year. One line (MIT, no key) from rba_mcp import client print ( client . latest ( " F1_1 " , series = " cash_rate_target " ). records [ - 1 ]. value ) # live AU.CASHRATE as of 2026-09-03: 4.35 pip install rba-mcp No key. MIT-licensed. Attribution and source URL come back with the number. Hosted gateway Use GET /v1/series/AU.CASHRATE/latest on api.ausdata.io with a free key from ausdata.io (500 calls/mo). Live 2026-09-06: cash 4.35 percent, trimmed-mean CPI 3.6 percent (2026-Q2), real rate 0.75 percent. Why the hosted path exists The RBA publishes the nominal cash rate. The ABS publishes inflation. Neither publishes the real cash rate (nominal minus trimmed-mean CPI). Use /v1/real-rate-regime for that join. Same envelope across nine AU sources: source, source_url, attribution, retrieved_at. MCP Wire ausdata-mcp via npx in Claude Desktop or Cursor. Sisters on PyPI run fully local with no key. What this is not Suburb-level property prices Live KYC / company-officer lookup 5-minute wholesale electricity bid stacks AU macro public data, one envelope, citations done for you. R users readrba by Matt Cowgill is the R equivalent. This is the Python / JS / agent path. Links Canonical: https://ausdata.io/blog/rba-cash-rate-python-api/ Free key: https://ausdata.io Series: https://ausdata.io/series/AU.CASHRATE PyPI: rba-mcp

2026-09-06 原文 →
AI 资讯

Checking If a Business's Google Profile Actually Matches Its Own Website

If you do local SEO work, you've run into this: a client's Google Business Profile says one phone number, their website footer says another, and nobody noticed until a customer called the wrong number. Or the postal code on the GBP listing is a leftover from an old office. This kind of drift is called a NAP (Name, Address, Phone) inconsistency, and it's widely cited as a local search ranking factor. But checking it by hand means opening every listing and every website side by side. I built Google Maps NAP Consistency Checker , an Apify Actor that takes Google Maps scraper output, fetches each business's own website (lightly: homepage plus one likely subpage), and checks whether the name, postal code, and phone number on the Google Business Profile actually show up on the site. What it does, and what it doesn't This Actor checks one thing: does a business's own website agree with its Google Business Profile on name, postal code, and phone number. It does not check third-party directories (Yelp, Facebook, etc.). That's a different problem with a different competitor landscape. It does not crawl an entire website; it fetches at most two pages per business (homepage, plus a subpage if one with a keyword like "contact" or "about" is linked from it). It does not use an LLM. It's regex and string matching against fetched text, which makes it fast, cheap, and predictable. There's no model that can hallucinate a match that isn't there. Businesses with no independent website (only a social profile, or nothing) are skipped entirely, because there's nothing to fetch and compare against. How it works For each place with a real website, the Actor: Checks robots.txt for that domain before fetching anything, and skips the business if the checker's user agent isn't allowed. Fetches the homepage HTML (up to 3 MB), strips <script> , <style> , and comments before converting to text, so JavaScript variables and tracking IDs don't get misread as phone numbers. Looks for an internal link

2026-09-06 原文 →
AI 资讯

Exit code 0 is a lie: 7 ways my unattended automation silently did nothing

I run about thirty scheduled jobs on a single Windows box. Some are scrapers, some generate content, some are trading bots, some just check that the other jobs are alive. Most of them were written and are maintained by an AI coding agent that I let run unattended. Over three months, every one of the failures below reported success . The scheduler said LastTaskResult = 0 . The logs looked fine or didn't exist. And nothing had happened. If you only take one thing from this post: stop checking exit codes, start checking artifacts. I'll get to why at the end. First, the seven ways I got lied to. 1. The wrapper that always returns 0 To stop console windows flashing on my desktop every few minutes, I wrapped each scheduled task in a tiny VBScript launcher: Set WshShell = CreateObject ( "WScript.Shell" ) WshShell . Run "cmd /c "" python job.py >> job.log 2>&1 "" " , 0 , True 0 hides the window. True waits for completion. I assumed True also meant the exit code came back. It does not. WshShell.Run used as a statement discards the return value, so wscript.exe exits 0 no matter what the child did. I found this because a content pipeline had been dead for five days while the scheduler reported green every single day. The fix is to call Run as a function and pass the value out: Set WshShell = CreateObject ( "WScript.Shell" ) exitCode = WshShell . Run ( "cmd /c "" python job.py >> job.log 2>&1 "" " , 0 , True ) WScript . Quit ( exitCode ) Note the parentheses — required when you're taking a return value. After fixing this across 17 launchers, one task showed a non-zero result for the first time in its life . It had been failing for weeks. 2. The last line of your batch file overwrites the exit code Fixed the launcher, still got false greens. The next layer down was a .cmd shim: node pipeline .js >> run .log 2 >& 1 echo [ done ] exit code %errorlevel% >> run .log That echo is the last command, echo always succeeds, so the batch file returns its exit code — zero — regardless of wh

2026-09-06 原文 →
AI 资讯

Scraping 150k+ Instagram followers reliably: batching, resume-on-error, and enrichment

I run a small AI/automation consultancy in Brazil, and a recent lead-research project needed the full follower list of a public Instagram profile — about 153,000 followers — plus enrichment (bio, public email/phone) to find business accounts worth contacting. The problem Pulling a list that size is never one API call. Instagram reports ~153,628 followers; you get them page by page, and any long-running extraction WILL hit a failed request eventually. If your pipeline can't resume, you start over from zero — which is expensive and slow. What I built The pipeline runs on n8n with Supabase as the datastore: Batched extraction — followers are downloaded in batches of up to 10,000 per cycle, on a schedule, instead of one giant run. Resume on error — every page cursor and count is persisted. When a request fails mid-run (in one run it stopped at 4,782 followers after 96 pages read), the job logs the error, emails me a status report, and picks up from the same point on the next cycle instead of restarting. Enrichment pass — a second workflow walks the stored followers and pulls profile details, flagging commercial accounts and any public email/phone in the bio. Personal/private accounts return no contact data, which the report counts separately. Email reports — each cycle sends me a summary: profile, followers reported vs. downloaded, pages read, batch name, and the exact error if one occurred. For the Instagram data layer I used HikerAPI — I tested a few other options first, and it won on pricing and rate limits for this volume. It handled the pagination fine: the run above made 100+ requests without me managing sessions or proxies myself. Tradeoffs / what didn't go perfectly Long extractions still fail sometimes (timeouts); resume logic is not optional at this scale, whatever API you use. Early days for me on this stack: so far it has worked well, but I'm still collecting more data before I'd call the pipeline battle-tested. I'll know more after a few full 150k-follower

2026-09-06 原文 →
产品设计

Trying VLA (Part 6): Controlling LeRobot with a SpaceMouse

Mapping SpaceMouse Controls to SO-101 Movements In the previous article, I connected the SpaceMouse to the PC and confirmed that all six types of input could be detected correctly. https://dev.to/takeofuture/trying-vla-part-5-setting-up-and-testing-a-spacemouse-eio Forward / Backward Left / Right Up / Down Pitch Roll Yaw During the SpaceMouse test, I confirmed the following input values. Forward horizontal = +Y Backward horizontal = -Y Left horizontal = -X Right horizontal = +X Up = +Z Down = -Z Forward tilt = +Pitch Backward tilt = -Pitch Left tilt = -Roll Right tilt = +Roll Left twist = -Yaw Right twist = +Yaw An important point here is that these values from the SpaceMouse are not sent directly to individual SO-101 motors . Conceptually, the flow from the SpaceMouse to the SO-101 looks like this: SpaceMouse ↓ x / y / z / roll / pitch / yaw ↓ SpaceMouse Teleoperator ↓ target_x / target_y / target_z target_wx / target_wy / target_wz ↓ Inverse Kinematics (IK) ↓ SO-101 Joint Positions ↓ SO-101 The SpaceMouse plugin treats the 6DoF input from the SpaceMouse as movement of the End Effector in Cartesian coordinates. The target movement is then converted into the required SO-101 joint angles using IK, or Inverse Kinematics . In other words, instead of directly specifying something like: "Move this motor by 5 degrees" we provide commands such as: "Move the End Effector slightly forward" "Move the End Effector slightly upward" "Rotate the End Effector slightly" The SpaceMouse provides these commands, and IK calculates how the individual joints need to move. Mapping Between SpaceMouse and LeRobot Coordinates There is one thing we need to be careful about here. The x and y values displayed by the SpaceMouse test do not directly become LeRobot's target_x and target_y . With the default SpaceMouse plugin configuration, the axes are mapped as follows: SpaceMouse y -> target_x SpaceMouse x -> target_y SpaceMouse z -> target_z SpaceMouse roll -> target_wx SpaceMouse pitch -> targ

2026-09-06 原文 →