废话
已经很久没有用过了,我的合伙人浑河学者最近要做自动驾驶仿真,我建议他使用webots来进行仿真,但是他想用matlab来写controller,这不,遇到问题了……
使用环境
- win10系统
- webots R2020a rev1 (官方发行版)
- Matlab R2016a
问题叙述
要开始,请键入以下项之一: helpwin、helpdesk 或 demo。 有关产品信息,请访问 www.mathworks.com。 错误: 文件:D:\Program Files\Webots\lib\controller\matlab\launcher.m 行:29 列:50 输入字符不是 MATLAB 语句或表达式中的有效字符。
》
问题分析
先来看一下为什么会报launcher.m
这个文件错误呢?在webots中,matlab调用的webotsAPI实际上是通过c API来实现的,这个调用操作实际上就是通过launcher.m
来进行的,并且其中还自动配置了环境变量,省去了我们配环境的繁琐操作。在使用matlab写控制器之前,需要给matlab安装MinGW GCC
,因为需要matlab与c的交互。对于安装过程这里不再赘述,但是此处有个坑需要强调一下:
MATLAB官网的安装包在安装的时候需要访问第三方MinGW网站来下载,但是实际上在安装的时候,matlab获取附加功能无法连接第三方网站(不知是否是我的matlab的问题),所以我们需要手动为matlab安装MinGW.
在目录D:\Program Files\Webots\lib\controller\matlab找到launcher.m
,发现第29行语法使用双引号""
,由于Matlab R2016不支持双引号字符串变量,当然会报错,Matlab R2019中不存在该问题。
手动安装MinGW,程序在附加功能管理
里面找不到MinGW列表,所以我们直接屏蔽第28-32行代码即可。
等等,好像哪里不对劲!
这些脚本文件都是在lib\controller\matlab下,为啥launcher.m
写的是'/lib/matlab'
?此处必有猫腻!!!!
Ctrl+F全部把/lib/matlab
替换成/lib/controller/matlab
,完美!
注意第15行代码字符串需要改成
../../..
save一下,你以为这就结束了?NO,还有一个文件需要修改:allincludes.h
同样的问题,路径对应错误:
继续Ctrl+F替换,保存!OK!!!
测试
相当完美!!!
继续废话
正当我准备去GitHub提交我修改的BUG时,发现已经有大佬在15day前修改过了,我哭了……
链接在这:https://github.com/cyberbotics/webots/pull/1378/files
所以我猜,下一个版本应该会修复这个BUG
贴上代码
launcher.m
:
% Launcher script for MATLAB Webots controllers
% useful env variables supplied by webots
WEBOTS_HOME = getenv('WEBOTS_HOME');
WEBOTS_CONTROLLER_NAME = getenv('WEBOTS_CONTROLLER_NAME');
WEBOTS_VERSION = getenv('WEBOTS_VERSION');
if isempty(WEBOTS_CONTROLLER_NAME)
disp('Entering test mode (normally launcher.m should be called by Webots, not from the MATLAB command line)');
disp(['Using MATLAB R' version('-release')]);
cd('../../..');
WEBOTS_HOME = pwd;
[status, cmdout] = system('msys64/mingw64/bin/webots.exe --version');
WEBOTS_VERSION = strrep(cmdout(17:end-1),'.','_');
cd('lib/controller/matlab');
disp(['Using Webots ' strrep(WEBOTS_VERSION,'_','.') ' from ' pwd ])
test_mode = true;
else
test_mode = false;
end
% add path to Webots API m-files
addpath([WEBOTS_HOME '/lib/controller/matlab']);
if ispc
setenv('MINGWROOT', strcat(WEBOTS_HOME,'\\msys64\\mingw64'));
libname = 'Controller';
% installed_addons = matlab.addons.installedAddons;
% installed = sum(installed_addons.Identifier == "ML_MINGW");
% if installed <= 0 || matlab.addons.isAddonEnabled('ML_MINGW') <= 0
% disp('The MATLAB "MinGW-w64 C/C++ Compiler" addon is not installed, please install it from: https://fr.mathworks.com/matlabcentral/fileexchange/52848-matlab-support-for-mingw-w64-c-c-compiler');
% end
addpath([WEBOTS_HOME '/msys64/mingw64/bin']);
else
libname = 'libController';
% add path to libController
addpath([WEBOTS_HOME '/lib/controller']);
end
try
% work in the system's temp dir so we have write access
cd(tempdir); % that supports non-ASCII character since MATLAB 2016a
% creates the base name of the protofile (without .m extension)
% we make the name dependant on matlab and webots versions, so a new file will be generated for any version change
% we need to replace the dots by underscores, because dots cause problems in the protofile
protofile = strrep(strrep(['protofile_matlab_' version('-release') '_webots_' WEBOTS_VERSION], '.', '_'), ' ', '_');
% another controller is currently generating the proto file: need to wait
lockfile = 'webots_matlab_lock';
counter = 1;
while exist(lockfile, 'file')
if (counter == 1)
disp(['Waiting up to 5 seconds for ' tempdir lockfile ' to be deleted by another MATLAB instance.']);
end
pause(1);
if (counter == 5)
disp(['Deleting ' tempdir lockfile '...'])
delete(lockfile);
end
counter = counter + 1;
end
libcontrollerloaded = false;
if ~exist([protofile '.m'], 'file')
% create a lock to prevent any other matlab controller from generating the proto file simultaneously
fid = fopen(lockfile, 'w');
fclose(fid);
disp(['Creating: ' tempdir protofile '.m']);
try
loadlibrary( ...
libname,'allincludes.h', ...
'mfilename',protofile, ...
'alias','libController', ...
'addheader','accelerometer.h', ...
'addheader','brake.h', ...
'addheader','camera.h', ...
'addheader','compass.h', ...
'addheader','connector.h', ...
'addheader','console.h', ...
'addheader','device.h', ...
'addheader','differential_wheels.h', ...
'addheader','display.h', ...
'addheader','distance_sensor.h', ...
'addheader','emitter.h', ...
'addheader','gps.h', ...
'addheader','gyro.h', ...
'addheader','inertial_unit.h', ...
'addheader','joystick.h', ...
'addheader','keyboard.h', ...
'addheader','led.h', ...
'addheader','lidar.h', ...
'addheader','light_sensor.h', ...
'addheader','motor.h', ...
'addheader','mouse.h', ...
'addheader','pen.h', ...
'addheader','position_sensor.h', ...
'addheader','radar.h', ...
'addheader','range_finder.h', ...
'addheader','receiver.h', ...
'addheader','robot.h', ...
'addheader','skin.h', ...
'addheader','speaker.h', ...
'addheader','supervisor.h', ...
'addheader','touch_sensor.h', ...
'addheader',['utils' filesep 'motion.h'], ...
'addheader',['utils' filesep 'system.h']);
disp('Load Library successful');
libcontrollerloaded = true;
catch ME % this happens with MATLAB R2015a only but seems to be harmless
if (version('-release') == '2015a')
loadlibrary(libname,protofile,'alias','libController');
libcontrollerloaded = true;
else
disp('Load Library failed.');
rethrow(ME);
loadlibrary = false;
end
end
delete(lockfile);
else
disp(['Using prototype file: ' tempdir protofile '.m']);
loadlibrary(libname,protofile,'alias','libController');
libcontrollerloaded = true;
end
if test_mode == true
unloadlibrary('libController');
cd([WEBOTS_HOME '/lib/controller/matlab']);
disp('Test successful.');
return
end
% initialize libController and redirect stdout/stderr
try
calllib('libController', 'wb_robot_init');
catch
calllib('libController', 'wb_robot_init_msvc');
end
% start controller
WEBOTS_PROJECT_UTF8 = wbu_system_getenv('WEBOTS_PROJECT');
WEBOTS_PROJECT = wbu_system_short_path(WEBOTS_PROJECT_UTF8);
cd([WEBOTS_PROJECT '/controllers/' WEBOTS_CONTROLLER_NAME]);
eval(WEBOTS_CONTROLLER_NAME);
catch ME
% display error message in Webots console
% use stderr to display message in red (this does not work on Windows)
err = getReport(ME, 'extended');
fprintf(2,'%s\n\n',err);
if ispc
if libcontrollerloaded
% only try to put the error on the console if the library has been loaded
calllib('libController', 'wb_console_print', err, 1);
exit(-1);
end
% on Windows, exiting systematically would imply to lose the error message
else
exit(-1);
end
end
allincludes.h
/*
This file is used by the loadlibrary() function in the launcher.m (MATLAB) file.
It contains all the headers files of Webots C-API.
*/
#define WB_MATLAB_LOADLIBRARY
#include "../../../include/controller/c/webots/accelerometer.h"
#include "../../../include/controller/c/webots/brake.h"
#include "../../../include/controller/c/webots/camera.h"
#include "../../../include/controller/c/webots/compass.h"
#include "../../../include/controller/c/webots/connector.h"
#include "../../../include/controller/c/webots/console.h"
#include "../../../include/controller/c/webots/device.h"
#include "../../../include/controller/c/webots/differential_wheels.h"
#include "../../../include/controller/c/webots/display.h"
#include "../../../include/controller/c/webots/distance_sensor.h"
#include "../../../include/controller/c/webots/emitter.h"
#include "../../../include/controller/c/webots/gps.h"
#include "../../../include/controller/c/webots/gyro.h"
#include "../../../include/controller/c/webots/inertial_unit.h"
#include "../../../include/controller/c/webots/joystick.h"
#include "../../../include/controller/c/webots/keyboard.h"
#include "../../../include/controller/c/webots/led.h"
#include "../../../include/controller/c/webots/lidar.h"
#include "../../../include/controller/c/webots/light_sensor.h"
#include "../../../include/controller/c/webots/motor.h"
#include "../../../include/controller/c/webots/mouse.h"
#include "../../../include/controller/c/webots/pen.h"
#include "../../../include/controller/c/webots/position_sensor.h"
#include "../../../include/controller/c/webots/radar.h"
#include "../../../include/controller/c/webots/range_finder.h"
#include "../../../include/controller/c/webots/receiver.h"
#include "../../../include/controller/c/webots/robot.h"
#include "../../../include/controller/c/webots/skin.h"
#include "../../../include/controller/c/webots/speaker.h"
#include "../../../include/controller/c/webots/supervisor.h"
#include "../../../include/controller/c/webots/touch_sensor.h"
#include "../../../include/controller/c/webots/utils/motion.h"
#include "../../../include/controller/c/webots/utils/system.h"
关于MATLAB R2019b检索不到的问题
博主还遇到一个问题,就是matlab R2019b,安装目录为D:\Program Files\Polyspace\R2019b
,而不是D:\Program Files\MATLAB\R2019b
,环境变量Path也没问题,在DOS下键入matlab
也可以启动matlab 2019,但是webots还是默认启动matlab 2016,如果删除matlab 2016的环境变量,则会报如下警告:
WARNING: To run Matlab controllers, you need to install Matlab 64-bit and ensure it is available from the DOS CMD.EXE console.
我的matlab2019是在Polyspace
文件夹下的,所以我怀疑webots只能链接MATLAB
文件夹下的程序, 凌波洞主老铁遇到这个问题,据描述,把Polyspace
重命名为MATLAB
下即可解决问题。(详情请见本文评论区)
读万卷书,也要行万里路!我是罗伯特祥,下次见!