V-REP的Lua在Linux上使用`tonumber`返回nil

我们开发了一个简单的 V-REP 仿真,在 OS X 上运作得非常好,但在 Linux (Ubuntu 15.04) 上不好使。主要的脚本语言是 Lua

我们附上以下代码(带有注释中的返回值),可惜在Linux上会返回 nil(但会在 OS X 上转换 e[3] 成为数字而不出问题):

e[3]                   -- -0.677782532263
type(e[3])             -- string
type(tonumber(e[3]))   -- nil

真正有趣的是,上述代码在 Lua 5.2.3 控制台中可以如预期那样运作(无论是在 OS X 还是 Linux 上)。然而,当在 Linux 上运行时,V-REP不能正确地将字符串转换为数字。

我们尝试了 32 位和 64 位 V-REP 版本,结果完全一样 - 始终为“nil”。请问您能指出我们可能遗漏的一些事情吗?无论是 Lua 还是 V-REP,都不是我们每天都在使用的工具。

编辑1: 我使用的是 Ubuntu 15.04。V-REP 使用的是 Lua 5.1,我的 Lua 版本:

$ apt-cache policy lua5.1
lua5.1:
  Installed: 5.1.5-7.1
  Candidate: 5.1.5-7.1
  Version table:
 *** 5.1.5-7.1 0
        500 http://cz.archive.ubuntu.com/ubuntu/ vivid/main amd64 Packages
        100 /var/lib/dpkg/status

在控制台中,我尝试了以下内容:

$ lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> e={[3]="-0.677782532263"}; print(e[3], type(e[3]), tonumber(e[3]), type(tonumber(e[3])))
-0.677782532263 string  -0.677782532263 number

点赞
用户1581558
用户1581558

错误的原因是 V-REP 使用的是 _Lua 5.1_,而我们测试的计算机对数字有不同的本地设置(linux 使用 LC_NUMERIC=cs_CZ.UTF-8,mac 可能使用 en_US)。

这意味着在 Mac 上 Lua 可以将字符串中的浮点数识别为数字,但在不同本地设置的 Linux 上却不能 - 它没有以逗号(例如 -3,513)作为本地所需的小数分隔符,所以返回了 nil。

解决方法是在运行 vrep 前将 LC_NUMERIC 标志设置为 en_US 本地,像这样:

...$ LC_NUMERIC=en_US.UTF-8 ./vrep

这将强制使用基于点的本地设置,并使 Lua 能够识别数字。

感谢 @Etan 提供的所有帮助,以及从正确的方向进行调查。

2016-04-07 14:26:30
用户4296784
用户4296784

另一种设置 Lua 代码的本地语言的方法是 os.setlocale("C")。

并非所有的系统都能在启动时更改任意应用程序的语言环境,有时需要更改整个系统的语言环境,这可能会对其他应用程序造成不便。如果与 V-REP 分发的脚本以 XML 文件的形式分发,其中分隔符为句点而不是逗号,则在调用 tonumber 函数之前,应该从 LUA 安装正确的控制台,而不是从外部通过打开环境变量的变量。

Lua 文档清楚地描述了 os.setLocale 函数的用途,并明确说明它影响字符串转换为数字的过程。因此,在调用转换函数之前,必须确保正确的设置。

此外,更改自身语言环境的脚本更具可移植性,因为不需要启动者知道应从外部指定哪些 V-REP 的环境变量。

2018-06-27 01:54:24