diff --git a/source/EV3.m b/source/EV3.m index 610693e852f655a5e09a9fca81926d7b296d5faa..cc7bbbea30b1a469baaab625767c76c9b12b00cd 100644 --- a/source/EV3.m +++ b/source/EV3.m @@ -1,4 +1,4 @@ -classdef EV3 < MaskedHandle +classdef EV3 < MaskedHandle % High-level class to work with physical bricks. % % This is the 'central' class (from user's view) when working with this toolbox. It @@ -295,11 +295,7 @@ classdef EV3 < MaskedHandle 'You have to call ev3.connect(...) first!']); end - ev3.commInterface.soundPlayTone(10, 1000, 100); - - if ev3.debug - fprintf('(DEBUG) EV3::beep: Sent ''soundPlayTone''-command\n'); - end + ev3.handleCommand(@soundPlayTone, 10, 1000, 100); end function playTone(ev3, volume, frequency, duration) @@ -322,11 +318,7 @@ classdef EV3 < MaskedHandle 'You have to call ev3.connect(...) first!']); end - ev3.commInterface.soundPlayTone(volume, frequency, duration); - - if ev3.debug - fprintf('(DEBUG) EV3::playTone: Sent ''soundPlayTone''-command\n'); - end + ev3.handleCommand(@soundPlayTone, volume, frequency, duration); end function stopTone(ev3) @@ -344,11 +336,7 @@ classdef EV3 < MaskedHandle 'You have to call ev3.connect(...) first!']); end - ev3.commInterface.soundStopTone(); - - if ev3.debug - fprintf('(DEBUG) EV3::stopTone: Called ''soundStopTone''-command\n'); - end + ev3.handleCommand(@soundStopTone); end function status = tonePlayed(ev3) @@ -370,11 +358,7 @@ classdef EV3 < MaskedHandle 'You have to call ev3.connect(...) first!']); end - status = ev3.commInterface.soundTest; - - if ev3.debug - fprintf('(DEBUG) EV3::tonePlayed: Called ''soundTest''-command\n'); - end + status = ev3.handleCommand(@soundTest); end %% Setter @@ -488,21 +472,30 @@ classdef EV3 < MaskedHandle end methods (Access = private) % Private brick functions that are wrapped by dependent params + function varargout = handleCommand(ev3, commandHandle, varargin) + % Execute a CommunicationInterface-method given as a handle + % + % As those methods have different, fixed numbers of output arguments, this quantity + % has to be retrieved first. + + if ev3.debug + fprintf('(DEBUG) Sending %s\n', func2str(commandHandle)); + end + + % Note: Arrg. MATLAB does not support nargout for class methods directly, so I have to + % do this ugly workaround using strings. See + % https://de.mathworks.com/matlabcentral/answers/96617-how-can-i-use-nargin-nargout-to-determine-the-number-of-input-output-arguments-of-an-object-method + nOut = nargout(strcat('CommunicationInterface>CommunicationInterface.', func2str(commandHandle))); + [varargout{1:nOut}] = commandHandle(ev3.commInterface, varargin{:}); + end + function bat = getBattery(ev3) % Retrieve batteryValue from brick in current mode. (Wrapped by EV3.batteryValue) if strcmpi(ev3.batteryMode, 'Percentage') - bat = ev3.commInterface.uiReadLbatt(); - - if ev3.debug - fprintf('(DEBUG) EV3::getBattery: Called ''uiReadLBatt''-command\n'); - end + bat = ev3.handleCommand(@uiReadLbatt); else - bat = ev3.commInterface.uiReadVbatt(); - - if ev3.debug - fprintf('(DEBUG) EV3::getBattery: Called ''uiReadVBatt''-command\n'); - end + bat = ev3.handleCommand(@uiReadVbatt); end end diff --git a/source/Motor.m b/source/Motor.m index b9887d67297fc49dbc69cb8316bda253072267c7..c5ed3bb23040e34d43a87d2095e0c754e556304a 100644 --- a/source/Motor.m +++ b/source/Motor.m @@ -272,10 +272,7 @@ classdef Motor < MaskedHandle & dynamicprops end - if motor.debug - fprintf('\n(DEBUG) Motor::start: Calling ''outputStart''-command on Port %s...\n', port2str('Motor', motor.port)); - end - motor.commInterface.outputStart(0, motor.port); + motor.handleCommand(@outputStart, 0, motor.port); motor.state.startedNotBusy = true; else @@ -287,41 +284,21 @@ classdef Motor < MaskedHandle & dynamicprops if strcmpi(motor.limitMode, 'Tacho') if motor.speedRegulation - if motor.debug - fprintf('\n(DEBUG) Motor::start: Calling ''outputStepSpeed''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - - motor.commInterface.outputStepSpeed(0, motor.port, motor.power,... + motor.handleCommand(@outputStepSpeed, 0, motor.port, motor.power,... motor.smoothStart, limit, motor.smoothStop,... motor.brakeMode_); else - if motor.debug - fprintf('\n(DEBUG) Motor::start: Calling ''outputStepPower''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - - motor.commInterface.outputStepPower(0, motor.port, motor.power,... + motor.handleCommand(@outputStepPower, 0, motor.port, motor.power,... motor.smoothStart, limit, motor.smoothStop,... motor.brakeMode_); end elseif strcmpi(motor.limitMode, 'Time') if motor.speedRegulation - if motor.debug - fprintf('\n(DEBUG) Motor::start: Calling ''outputTimeSpeed''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - - motor.commInterface.outputTimeSpeed(0, motor.port, motor.power,... + motor.handleCommand(@outputTimeSpeed, 0, motor.port, motor.power,... motor.smoothStart, limit, motor.smoothStop,... motor.brakeMode_); else - if motor.debug - fprintf('\n(DEBUG) Motor::start: Calling ''outputTimePower''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - - motor.commInterface.outputTimePower(0, motor.port, motor.power,... + motor.handleCommand(@outputTimePower, 0, motor.port, motor.power,... motor.smoothStart, limit, motor.smoothStop,... motor.brakeMode_); end @@ -349,10 +326,7 @@ classdef Motor < MaskedHandle & dynamicprops return; end - if motor.debug - fprintf('\n(DEBUG) Motor::stop: Calling ''outputStop''-command on Port %s...\n', port2str('Motor', motor.port)); - end - motor.commInterface.outputStop(0, motor.port, motor.brakeMode_); + motor.handleCommand(@outputStop, 0, motor.port, motor.brakeMode_); motor.state.startedNotBusy = false; end @@ -473,19 +447,11 @@ classdef Motor < MaskedHandle & dynamicprops if strcmpi(motor.limitMode, 'Tacho') - if motor.debug - fprintf(['\n(DEBUG) Motor::syncedStart: Calling ''outputStepSync''-command on ' ,... - 'Ports %s and %s.\n'], port2str('Motor', motor.port), port2str('Motor', syncMotor.port)); - end - motor.commInterface.outputStepSync(0, motor.port+syncMotor.port, ... + motor.handleCommand(@outputStepSync, 0, motor.port+syncMotor.port, ... motor.power, turnRatio, ... motor.limitValue, motor.brakeMode_); elseif strcmpi(motor.limitMode, 'Time') - if motor.debug - fprintf('\n(DEBUG) Motor::start: Calling ''outputStepSync''-command on Ports %s and %s.\n',... - port2str('Motor', motor.port), port2str('Motor', syncMotor.port)); - end - motor.commInterface.outputTimeSync(0, motor.port+syncMotor.port, ... + motor.handleCommand(@outputTimeSync, 0, motor.port+syncMotor.port, ... motor.power, turnRatio, ... motor.limitValue, motor.brakeMode_); end @@ -527,11 +493,7 @@ classdef Motor < MaskedHandle & dynamicprops syncMotor.applyState(); % Synced stopping - if motor.debug - fprintf('\n(DEBUG) Motor::syncedStop: Calling ''outputStop''-command on Ports %s and %s.\n', ... - port2str('Motor', motor.port), port2str('Motor', syncMotor.port)); - end - motor.commInterface.outputStop(0, motor.port+syncMotor.port, motor.brakeMode_); + motor.handleCommand(@outputStop, 0, motor.port+syncMotor.port, motor.brakeMode_); % On next start, both motors have to send power-opcode again if motor.state.sendPowerOnSet @@ -590,11 +552,7 @@ classdef Motor < MaskedHandle & dynamicprops port2str('Motor', motor.port)); end - if motor.debug - fprintf('\n(DEBUG) Motor::internalReset: Calling ''outputReset''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - motor.commInterface.outputReset(0, motor.port); + motor.handleCommand(@outputReset, 0, motor.port); end function resetTachoCount(motor) @@ -609,11 +567,7 @@ classdef Motor < MaskedHandle & dynamicprops port2str('Motor', motor.port)); end - if motor.debug - fprintf('\n(DEBUG) Motor::resetTachoCount: Calling ''outputClrCount''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - motor.commInterface.outputClrCount(0, motor.port); + motor.handleCommand(@outputClrCount, 0, motor.port); end function setBrake(motor, brake) @@ -963,7 +917,24 @@ classdef Motor < MaskedHandle & dynamicprops end end - methods (Access = private) % Private functions that directly interact with commLayer + methods (Access = private) % Private functions that directly interact with commLayer# + function varargout = handleCommand(motor, commandHandle, varargin) + % Execute a CommunicationInterface-method given as a handle + % + % As those methods have different, fixed numbers of output arguments, this quantity + % has to be retrieved first. + + if motor.debug + fprintf('(DEBUG) Sending %s\n', func2str(commandHandle)); + end + + % Note: Arrg. MATLAB does not support nargout for class methods directly, so I have to + % do this ugly workaround using strings. See + % https://de.mathworks.com/matlabcentral/answers/96617-how-can-i-use-nargin-nargout-to-determine-the-number-of-input-output-arguments-of-an-object-method + nOut = nargout(strcat('CommunicationInterface>CommunicationInterface.', func2str(commandHandle))); + [varargout{1:nOut}] = commandHandle(motor.commInterface, varargin{:}); + end + function success = setPower(motor, power) % Sets given power value on the physical Brick. % @@ -983,15 +954,9 @@ classdef Motor < MaskedHandle & dynamicprops end; if motor.currentSpeedRegulation - if motor.debug - fprintf('\n(DEBUG) Motor::setPower: Calling ''outputSpeed''-command on Port %s...\n', port2str('Motor', motor.port)); - end - motor.commInterface.outputSpeed(0, motor.port, power); + motor.handleCommand(@outputSpeed, 0, motor.port, power); else - if motor.debug - fprintf('\n(DEBUG) Motor::setPower: Calling ''outputPower''-command on Port %s...\n', port2str('Motor', motor.port)); - end - motor.commInterface.outputPower(0, motor.port, power); + motor.handleCommand(@outputPower, 0, motor.port, power); end success = true; return; @@ -1002,12 +967,7 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::getTypeMode: Motor-Object not connected to comm handle.'); end - if motor.debug - fprintf('\n(DEBUG) Motor::getTypeMode: Calling ''inputDeviceGetTypeMode''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - - [typeNo,modeNo] = motor.commInterface.inputDeviceGetTypeMode(0, motor.portInput); + [typeNo, modeNo] = motor.handleCommand(@inputDeviceGetTypeMode, 0, motor.portInput); type = DeviceType(typeNo); mode = DeviceMode(type,modeNo); end @@ -1017,11 +977,7 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::getStatus: Motor-Object not connected to comm handle.'); end - if motor.debug - fprintf('\n(DEBUG) Motor::getStatus: Calling ''inputDeviceGetConnection''-command on Port %s...\n',... - port2str('Motor', motor.port)); - end - statusNo = motor.commInterface.inputDeviceGetConnection(0, motor.portInput); + statusNo = motor.handleCommand(@inputDeviceGetConnection, 0, motor.portInput); status = ConnectionType(statusNo); end @@ -1030,17 +986,11 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::getTachoCount: Motor-Object not connected to comm handle.'); end - if motor.debug - fprintf('\n(DEBUG) Motor::getTachoCount: Calling ''outputGetCount''-command on Port %s...\n', port2str('Motor', motor.port)); - end - cnt = motor.commInterface.outputGetCount(0, motor.portNo); + cnt = motor.handleCommand(@outputGetCount, 0, motor.portNo); end function cnt = getInternalTachoCount(motor) - if motor.debug - fprintf('\n(DEBUG) Motor::getInternalTachoCount: Calling ''outputRead''-command on Port %s...\n', port2str('Motor', motor.port)); - end - [~, cnt] = motor.commInterface.outputRead(0, motor.portNo); + [~, cnt] = motor.handleCommand(@outputRead, 0, motor.portNo); end function speed = getSpeed(motor) @@ -1048,10 +998,7 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::getSpeed: Motor-Object not connected to comm handle.'); end - if motor.debug - fprintf('\n(DEBUG) Motor::getSpeed: Calling ''inputReadSI''-command on Port %s...\n', port2str('Motor', motor.port)); - end - speed = motor.commInterface.inputReadSI(0, motor.portInput, DeviceMode.Motor.Speed); + speed = motor.handleCommand(@inputReadSI, 0, motor.portInput, DeviceMode.Motor.Speed); end function busy = getBusyFlag(motor) @@ -1067,10 +1014,7 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::getBusyFlag: Motor-Object not connected to comm handle.'); end - if motor.debug - fprintf('\n(DEBUG) Motor::getBusyFlag: Calling ''outputTest''-command on Port %s...\n', port2str('Motor', motor.port)); - end - busy = motor.commInterface.outputTest(0, motor.port); + busy = motor.handleCommand(@outputTest, 0, motor.port); end function applyBrake(motor) @@ -1083,18 +1027,13 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::applyBrake: Can''t apply brake because Motor is moving'); end - if motor.debug - fprintf(['\n(DEBUG) Motor::applyBrake: Calling ''outputPower'', ''outputStart'' and' ,... - '''outputStop'' on Port %s...\n'], port2str('Motor', motor.port)); - end - if motor.speedRegulation - motor.commInterface.outputPower(0, motor.port, 0); + motor.handleCommand(@outputPower, 0, motor.port, 0); else - motor.commInterface.outputSpeed(0, motor.port, 0); + motor.handleCommand(@outputSpeed, 0, motor.port, 0); end - motor.commInterface.outputStart(0, motor.port); - motor.commInterface.outputStop(0, motor.port, BrakeMode.Brake); + motor.handleCommand(@outputStart, 0, motor.port); + motor.handleCommand(@outputStop, 0, motor.port, BrakeMode.Brake); end function releaseBrake(motor) @@ -1107,17 +1046,13 @@ classdef Motor < MaskedHandle & dynamicprops error('Motor::releaseBrake: Can''t release brake because Motor is moving'); end - if motor.debug - fprintf(['\n(DEBUG) Motor::releaseBrake: Calling ''outputPower'', ''outputStart'' and' ,... - '''outputStop'' on Port %s...\n'], port2str('Motor', motor.port)); - end if motor.speedRegulation - motor.commInterface.outputPower(0, motor.port, 0); + motor.handleCommand(@outputPower, 0, motor.port, 0); else - motor.commInterface.outputSpeed(0, motor.port, 0); + motor.handleCommand(@outputSpeed, 0, motor.port, 0); end - motor.commInterface.outputStart(0, motor.port); - motor.commInterface.outputStop(0, motor.port, BrakeMode.Coast); + motor.handleCommand(@outputStart, 0, motor.port); + motor.handleCommand(@outputStop, 0, motor.port, BrakeMode.Coast); end end diff --git a/source/Sensor.m b/source/Sensor.m index f89b80f8c8460d1e3c1e6031ab8c469fc5bbc1e8..5e1c82947200b6c20cc13ebb9233d583be3111d1 100644 --- a/source/Sensor.m +++ b/source/Sensor.m @@ -252,11 +252,7 @@ classdef Sensor < MaskedHandle % warning(['Sensor::reset: Current version of reset resets ALL devices, that is, ',... % 'all motor tacho counts and all other sensor counters!']); - if sensor.debug - fprintf('\n(DEBUG) Sensor::reset: Calling ''inputReadSI''-command on Port %d...\n',... - sensor.port+1); - end - sensor.commInterface.inputDeviceClrAll(0); + sensor.handleCommand(@inputDeviceClrAll, 0); end %% Setter @@ -394,11 +390,7 @@ classdef Sensor < MaskedHandle sensor.port+1); end - if sensor.debug - fprintf('\n(DEBUG) Sensor::setMode: Calling ''inputReadSI''-command on Port %d...\n',... - sensor.port+1); - end - sensor.commInterface.inputReadSI(0, sensor.port, mode); % Reading a value implicitly + sensor.handleCommand(@inputReadSI, 0, sensor.port, mode); % Reading a value implicitly % sets the mode. end @@ -431,11 +423,7 @@ classdef Sensor < MaskedHandle mode = sensor.mode; end - if sensor.debug - fprintf('\n(DEBUG) Sensor::getValue: Calling ''inputReadSI''-command on Port %d...\n',... - sensor.port+1); - end - val = sensor.commInterface.inputReadSI(0, sensor.port, sensor.mode); + val = sensor.handleCommand(@inputReadSI, 0, sensor.port, sensor.mode); if strcmp(class(sensor.mode), 'DeviceMode.Color') @@ -446,11 +434,7 @@ classdef Sensor < MaskedHandle % See note if isnan(val) - if sensor.debug - fprintf('\n(DEBUG) Sensor::getValue: Calling ''inputReadSI''-command on Port %d...\n',... - sensor.port+1); - end - val = sensor.commInterface.inputReadSI(0, sensor.port, sensor.mode); + val = sensor.handleCommand(@inputReadSI, 0, sensor.port, sensor.mode); end end @@ -459,12 +443,7 @@ classdef Sensor < MaskedHandle error('Sensor::getStatus: Sensor-Object not connected to comm handle.'); end - if sensor.debug - fprintf(['\n(DEBUG) Sensor::getStatus: Calling ''inputDeviceGetConnection''-command on ' ,... - 'Port %d...\n'], sensor.port+1); - end - - statusNo = sensor.commInterface.inputDeviceGetConnection(0, sensor.port); + statusNo = sensor.handleCommand(@inputDeviceGetConnection, 0, sensor.port); status = ConnectionType(statusNo); end @@ -475,13 +454,9 @@ classdef Sensor < MaskedHandle type = DeviceType.Error; - if sensor.debug - fprintf(['\n(DEBUG) Sensor::getStatus: Calling ''inputDeviceGetConnection''-command on ' ,... - 'Port %d...\n'], sensor.port+1); - end for i = 1:10 try - [typeNo,modeNo] = sensor.commInterface.inputDeviceGetTypeMode(0, sensor.port); + [typeNo,modeNo] = sensor.handleCommand(@inputDeviceGetTypeMode, 0, sensor.port); type = DeviceType(typeNo); catch ME continue; @@ -498,6 +473,25 @@ classdef Sensor < MaskedHandle end + methods (Access = private) + function varargout = handleCommand(sensor, commandHandle, varargin) + % Execute a CommunicationInterface-method given as a handle + % + % As those methods have different, fixed numbers of output arguments, this quantity + % has to be retrieved first. + + if sensor.debug + fprintf('(DEBUG) Sending %s\n', func2str(commandHandle)); + end + + % Note: Arrg. MATLAB does not support nargout for class methods directly, so I have to + % do this ugly workaround using strings. See + % https://de.mathworks.com/matlabcentral/answers/96617-how-can-i-use-nargin-nargout-to-determine-the-number-of-input-output-arguments-of-an-object-method + nOut = nargout(strcat('CommunicationInterface>CommunicationInterface.', func2str(commandHandle))); + [varargout{1:nOut}] = commandHandle(sensor.commInterface, varargin{:}); + end + end + methods (Access = ?EV3) function connect(sensor,commInterface) %connect Connects Sensor-object to physical brick