Alternative to vJoy and FreePIE joystick and input emulators on Linux

news/2025/1/8 5:03:30/

在这里插入图片描述

这是我之前在个人网站上发布的一篇旧博客文章。我正在将所有内容转移到CSDN。感谢阅读!


This project is one step forward toward setting up universal mouse steering in racing games on Linux. Some games come with mouse support out of the box, while other games require additional setup. The game in question is Rigs of Rods – an open-source vehicle sandbox-simulator that is available on both Windows and Linux platforms. This game does not support mouse steering by default, however there are instructions on how to configure this function by creating a virtual joystick and binding it to mouse and keyboard inputs. Unfortunately, those instructions are written for Windows and require two pieces of software that aren’t readily available on Linux – vJoy and FreePIE.

We need 1) to read mouse output, specifically x and y axes values and 2) create a virtual joystick to adapt said mouse output to joystick input. A brief search online revealed the evdev interface that “serves the purpose of passing events generated in the kernel directly to userspace through character devices” (https://python-evdev.readthedocs.io/en/latest/index.html). The python-evdev package is a convenient Python wrapper around the interface which can be installed with pip3 install python-evdev. The second piece of the puzzle is python-uinput package which is the “interface to Linux uinput kernel module which allows attaching userspace device drivers into kernel” (https://github.com/pyinput/python-uinput); it can be installed with pip3 install python-uinput.

Below is the final script and explanation.

python">import evdev
import uinputRANGE = 65536  # 0 - 65535
HALF_RANGE = RANGE // 2def main():# Search for all connected input devicesdevices = [evdev.InputDevice(path) for path in evdev.list_devices()]# Find a mousemouse = Nonefor device in devices:if "mouse" in device.name.lower():mouse = devicebreakprint(mouse.capabilities(verbose=True))# Create a simple joystick with two main axesjoystick = (uinput.ABS_X + (-HALF_RANGE, HALF_RANGE, 0, 0),uinput.ABS_Y + (-HALF_RANGE, HALF_RANGE, 0, 0),)# Read mouse events and convert them to joystick inputswith uinput.Device(joystick) as j:for event in mouse.read_loop():  # runs in a constant loopif event.type == evdev.ecodes.EV_ABS:if event.code == evdev.ecodes.ABS_X:print("X:", event.value - HALF_RANGE)j.emit(uinput.ABS_X, event.value - HALF_RANGE)if event.code == evdev.ecodes.ABS_Y:print("Y:", event.value - HALF_RANGE)j.emit(uinput.ABS_Y, event.value - HALF_RANGE)if __name__ == "__main__":main()

The script needs to be run with sudo, as we read /dev/input/ which requires superuser access

First, we search for all the connected input devices and filter the first device with mouse in its name which is typically the only mouse device in the system (laptop touchpads have touchpad in their names). Second, we print its capabilities to find the device layout, the type of axes and codes as well as their minimum and maximum range values. We store the max range as a constant RANGE for later use.

After that, we create a virtual joystick device with a simple layout – x and y axes. These axes require min and max range definitions that typically revolve around 0 meaning that every value below 0 represents left and up directions (depending on an axis) and everything above 0 – right and down directions.
在这里插入图片描述
Source: https://docs.wpilib.org/en/stable/docs/software/basic-programming/joystick.html

Because the reported mouse values are in the range of 0 - 65535, we need to clamp those values so that they wrap around 0 – the range of -32768 and +32768 for 1:1 motion range. For that we use the previously assigned constant HALF_RANGE which is RANGE divided by 2. In order to adapt mouse values to joystick values we subtract 32768 from every mouse value that we read: 1 becomes -32767, 2 becomes -32766, etc.

Finally, we emit those new values on respective joystick axes and print them in terminal for debugging.
在这里插入图片描述
In order to see our virtual joystick in action, we can install the jstest-gtk program which is available through every distribution’s package manager.

The joystick is identified as python-uinput and contains 2 axes and 0 buttons as expected. It is only available when the script is running and will eject on program exit (you may need to click Refresh for the joystick to appear). To terminate the program we can press Ctrl-c or close the terminal.

在这里插入图片描述
Here is the result – mouse cursor movement is directly translated into joystick movement:

演示

The next step is to add buttons to the joystick and map them to appropriate keyboard and/or mouse keys which should be easy to do by reading the documentation.


http://www.ppmy.cn/news/1561466.html

相关文章

明源地产ERP VisitorWeb_XMLHTTP.aspx SQL注入漏洞复现

0x01 产品简介 明源地产ERP是一款专门为房地产行业设计的企业资源规划(ERP)系统,旨在帮助房地产企业实现全面的信息化管理,提高运营效率和管理水平。系统涵盖了项目管理、财务管理、供应链管理、客户关系管理(CRM)、人力资源管理等多个核心功能模块,通过整合企业的各个…

flink的EventTime和Watermark

时间机制 Flink中的时间机制主要用在判断是否触发时间窗口window的计算。 在Flink中有三种时间概念:ProcessTime、IngestionTime、EventTime。 ProcessTime:是在数据抵达算子产生的时间(Flink默认使用ProcessTime) IngestionT…

哦?将文本转换为专业流程图的终极解决方案?

前言 今天介绍的这款工具号称是将文本转换成专业流程图的终极解决方案。一起来看看是否能满足你的需求吧。 首页 平平无奇的首页(通常地下隐藏着不平常的东西),和我们之前介绍过的工具类似,核心就是我们中间的文本输入框。在输入…

【Python】基于blind-watermark库添加图片盲水印

blind-watermark 是一个用于在图像中添加和提取盲水印的 Python 库。盲水印是一种嵌入信息(如水印)到图像中的方法,使得水印在视觉上不可见,但在需要时可以通过特定的算法进行提取。以下是如何使用 blind-watermark 库来添加和提取…

君正T41交叉编译ffmpeg、opencv并做h264软解,利用君正SDK做h264硬件编码

目录 1 交叉编译ffmpeg----错误解决过程,不要看 1.1 下载源码 1.2 配置 1.3 编译 安装 1.3.1 报错:libavfilter/libavfilter.so: undefined reference to fminf 1.3.2 报错:error: unknown type name HEVCContext; did you mean HEVCPr…

Fastlio_localization的完整跑通记录,包括源码获取、编译、地图制作、运行及运行视频、脚本修改、结果保存等(跑通官方数据集以及Apollo数据集)

这篇文章做一个Fastlio_localization(以下简称fastlio_lc)的跑通记录文档。 步骤包括:源码获取、数据集获取、环境配置、源码编译、定位地图制作、基于数据集的脚本修改、源码运行、定位结果保存txt 等步骤 1.源码获取 1.直接进入github上下载,地址为&…

爬虫基础之爬取表情包GIF

网站地址 : 热门表情_发表情,表情包大全fabiaoqing.com 爬取思路: 通过开发者工具找到包含页面表情包的数据包 通过re parsel css等解析提取数据 爬取步骤: 一. 请求数据 模拟浏览器向服务器发送请求 打开F12 or 右击开发者模式 CtrlF 打开搜索框 输入要…

深入浅出 Pytest:自动化测试的最佳实践 pytest教程 程序测试 单元化测试

一、用法 .1 断言 在测试函数中用assert(断言)来判断测试是否符合预期。 # 一个成功的测试函数def test_passing():assert (1, 2, 3) (1, 2, 3)# 一个失败的测试函数def test_failing():assert (1, 2, 3) (3, 2, 1)assert 语句本质上是用于检查一个表…