diff --git a/source/EV3.m b/source/EV3.m index cc7bbbea30b1a469baaab625767c76c9b12b00cd..239698e4aa5eecd9b9df2d2d187256fec30a2428 100644 --- a/source/EV3.m +++ b/source/EV3.m @@ -268,12 +268,6 @@ classdef EV3 < MaskedHandle %% Device functions function stopAllMotors(ev3) % Sends a stop-command to all motor-ports. - - if ~ev3.isConnected - error(['EV3::stopAllMotors: Brick-Object not connected physical brick. ',... - 'You have to call ev3.connect(...) first!']); - end - ev3.commInterface.outputStopAll(); end @@ -289,12 +283,6 @@ classdef EV3 < MaskedHandle % b.connect('bt', 'serPort', '/dev/rfcomm0'); % |br| % b.beep(); % |br| % - - if ~ev3.isConnected - error(['EV3::beep: Brick-Object not connected physical brick. ',... - 'You have to call ev3.connect(...) first!']); - end - ev3.handleCommand(@soundPlayTone, 10, 1000, 100); end @@ -312,12 +300,6 @@ classdef EV3 < MaskedHandle % b.playTone(40, 5000, 1000); % Plays tone with 40% volume and 5000Hz for 1 % second. |br| % - - if ~ev3.isConnected - error(['EV3::isConnected: Brick-Object not connected physical brick. ',... - 'You have to call ev3.connect(...) first!']); - end - ev3.handleCommand(@soundPlayTone, volume, frequency, duration); end @@ -330,12 +312,6 @@ classdef EV3 < MaskedHandle % b.playTone(10,100,100000000); % Accidentally given wrong tone duration :) |br| % b.stopTone(); % Stops tone immediately. |br| % - - if ~ev3.isConnected - error(['EV3::stopTone: Brick-Object not connected physical brick. ',... - 'You have to call ev3.connect(...) first!']); - end - ev3.handleCommand(@soundStopTone); end @@ -352,12 +328,6 @@ classdef EV3 < MaskedHandle % pause(0.5); % Small pause is necessary as tone does not start instantaneously |br| % b.tonePlayed(); % -> Outputs 1 to console. |br| % - - if ~ev3.isConnected - error(['EV3::tonePlayed: Brick-Object not connected physical brick. ',... - 'You have to call ev3.connect(...) first!']); - end - status = ev3.handleCommand(@soundTest); end @@ -442,7 +412,7 @@ classdef EV3 < MaskedHandle %% Getter function bat = get.batteryValue(ev3) if ~ev3.isConnected - warning(ID('noConnection'), 'EV3::getBattery: EV3-Object not connected to physical EV3.'); + warning(ID('noConnection'), 'EV3-Object not connected to physical EV3.'); bat = 0; return; @@ -477,7 +447,15 @@ classdef EV3 < MaskedHandle % % As those methods have different, fixed numbers of output arguments, this quantity % has to be retrieved first. - + + if ~ev3.isConnected + msg = ['Brick-Object not connected physical brick. ',... + 'You have to call connect(...) first!']; + id = [ID(), ':', 'NotConnected']; + + throw(MException(id, msg)); + end + if ev3.debug fprintf('(DEBUG) Sending %s\n', func2str(commandHandle)); end @@ -486,12 +464,27 @@ classdef EV3 < MaskedHandle % 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{:}); + + try + [varargout{1:nOut}] = commandHandle(ev3.commInterface, varargin{:}); + catch ME + %ev3.detectedCommError(ME.identifier, ME.message); + if ~isempty(strfind(exceptionID, 'CommError')) + warning('Lost connection to the Brick!'); + ev3.disconnect(); + else + warning('Something went wrong. Trying to reset the connection...'); + ev3.disconnect(); + ev3.connect(); + end + + throw(exception); + end end function bat = getBattery(ev3) - % Retrieve batteryValue from brick in current mode. (Wrapped by EV3.batteryValue) - + % Retrieve batteryValue from brick in current mode. (Wrapped by get.batteryValue) + if strcmpi(ev3.batteryMode, 'Percentage') bat = ev3.handleCommand(@uiReadLbatt); else diff --git a/source/Motor.m b/source/Motor.m index c5ed3bb23040e34d43a87d2095e0c754e556304a..a0ed2715c26aa0fb218c7bd8aae00e55f314f6af 100644 --- a/source/Motor.m +++ b/source/Motor.m @@ -199,13 +199,11 @@ classdef Motor < MaskedHandle & dynamicprops function start(motor) % Starts the motor. - if ~motor.connectedToBrick - error('Motor::start: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected - error('Motor::start: No physical motor connected to Port %s',... + if ~motor.physicalMotorConnected + error('Could not detect motor at Port %s',... port2str('Motor', motor.port)); elseif motor.isRunning - error('Motor::start: Motor is already running!'); + error('Motor is already running!'); end if motor.speedRegulation ~= motor.currentSpeedRegulation @@ -278,7 +276,7 @@ classdef Motor < MaskedHandle & dynamicprops else limit = motor.limitValue - (motor.smoothStart + motor.smoothStop); if limit < 0 - error(['Motor::start: smoothStart/Stop invalid. ' ,... + error(['smoothStart/Stop invalid. ' ,... 'smoothStart + smoothStop has to be smaller than limitValue.']); end @@ -316,10 +314,8 @@ classdef Motor < MaskedHandle & dynamicprops % % See also MOTOR.START, MOTOR.SYNCEDSTOP / :meth:`start`, :meth:`syncedStop` - if ~motor.connectedToBrick - error('Motor::stop: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected - error('Motor::stop: No physical motor connected to Port %s',... + if ~motor.physicalMotorConnected + error('Could not detect motor at Port %s',... port2str('Motor', motor.port)); elseif motor.isSynced && motor.isRunning motor.syncedStop(); @@ -377,32 +373,30 @@ classdef Motor < MaskedHandle & dynamicprops % Check parameters if ~isDeviceValid('Motor', syncMotor) - error('Motor::syncedStart: Given motor to sync with is not a valid motor object.'); + error('Given motor to sync with is not a valid motor object.'); elseif ~isempty(varargin) if length(varargin)~=2 - error(['Motor::syncedStart: Wrong number of input arguments. ' ,... + error(['Wrong number of input arguments. ' ,... 'Possible input: ''turnRatio'', value (with value in [-200,200])']); end parameter = varargin{1}; turnRatio = varargin{2}; if ~strcmpi(parameter, 'turnRatio') || ~isnumeric(turnRatio) || ... turnRatio<-200 || turnRatio > 200 - error(['Motor::syncedStart: Wrong format of input arguments. Possible ',... + error(['Wrong format of input arguments. Possible ',... 'input: ''turnRatio'', value (with value in [-200,200])']); end end % Check connection and motor parameter - if ~motor.connectedToBrick || ~syncMotor.connectedToBrick - error('Motor::syncedStart: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected || ~syncMotor.physicalMotorConnected - error('Motor::syncedStart: No physical motor connected to Port %s or %s.',... + if ~motor.physicalMotorConnected || ~syncMotor.physicalMotorConnected + error('Could not detect motor at Port %s or %s.',... port2str('Motor', motor.port), port2str('Motor', syncMotor.port)); elseif motor.speedRegulation - error(['Motor::syncedStart: Cannot run motors synchronized if ',... + error(['Cannot run motors synchronized if ',... 'speedRegulation is turned on.']); elseif motor.isRunning || syncMotor.isRunning - error('Motor::syncedStart: One of the motors is already running!'); + error('One of the motors is already running!'); end % If the motor coasts into its stops, the internal tachocount has to be reset @@ -467,7 +461,7 @@ classdef Motor < MaskedHandle & dynamicprops % See also MOTOR.SYNCEDSTART, MOTOR.STOP / :meth:`syncedStart`, :meth:`stop` if ~motor.isSynced - error('Motor::syncedStop: Motor has not been started synchronized with another.'); + error('Motor has not been started synchronized with another.'); else % Retrieve synced motor from cache if motor.isMaster @@ -481,10 +475,8 @@ classdef Motor < MaskedHandle & dynamicprops end end - if ~motor.connectedToBrick || ~syncMotor.connectedToBrick - error('Motor::syncedStop: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected || ~syncMotor.physicalMotorConnected - error('Motor::syncedStop: No physical motor connected to either Port %s or %s.',... + if ~motor.physicalMotorConnected || ~syncMotor.physicalMotorConnected + error('Could not detect motor at Port %s or %s.',... port2str('Motor', motor.port), port2str('Motor', syncMotor.port)); end @@ -518,10 +510,6 @@ classdef Motor < MaskedHandle & dynamicprops % * Workaround: Poll isRunning until it is false (No need to check if motor is % connected as speed correctly returns 0 if it's not) - if ~motor.connectedToBrick - error('Motor::waitFor: Motor-Object not connected to comm handle.'); - end - while motor.isRunning pause(0.03); end @@ -544,11 +532,8 @@ classdef Motor < MaskedHandle & dynamicprops % % See also MOTOR.RESETTACHOCOUNT / :attr:`resetTachoCount` - if ~motor.connectedToBrick - error(['Motor::internalReset: Motor-Object not connected to brick handle.',... - 'You have to call motor.connect(brick) first!']); - elseif ~motor.physicalMotorConnected - error('Motor::internalReset: No physical motor connected to Port %s',... + if ~motor.physicalMotorConnected + error('Could not detect motor at Port %s',... port2str('Motor', motor.port)); end @@ -560,10 +545,8 @@ classdef Motor < MaskedHandle & dynamicprops % % See also MOTOR.TACHOCOUNT / :attr:`tachoCount` - if ~motor.connectedToBrick - error('Motor::resetTachoCount: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected - error('Motor::resetTachoCount: No physical motor connected to Port %s',... + if ~motor.physicalMotorConnected + error('Could not detect motor at Port %s',... port2str('Motor', motor.port)); end @@ -583,7 +566,7 @@ classdef Motor < MaskedHandle & dynamicprops % See also MOTOR.BRAKEMODE / :attr:`brakeMode` if ~isBool(brake) - error('Motor::setBrake: Given parameter is not a valid bool.'); + error('Given parameter is not a valid bool.'); else brake = str2bool(brake); end @@ -601,10 +584,10 @@ classdef Motor < MaskedHandle & dynamicprops %% Setter function set.power(motor, power) if ~isnumeric(power) - error('Motor::set.power: Given parameter is not a numeric.'); + error('Given parameter is not a numeric.'); elseif power<-100 || power>100 - warning('Motor::set.power: Motor power has to be an element of [-100,100]!'); - error('Motor::set.power: Given motor power is out of bounds.'); + warning('Motor power has to be an element of [-100,100]!'); + error('Given motor power is out of bounds.'); end motor.power = power; % Set power parameter. @@ -621,7 +604,7 @@ classdef Motor < MaskedHandle & dynamicprops function set.speedRegulation(motor, speedRegulation) if ~isBool(speedRegulation) - error('Motor::set.speedRegulation: Given parameter is not a bool.'); + error('Given parameter is not a bool.'); end speedRegulation = str2bool(speedRegulation); @@ -643,7 +626,7 @@ classdef Motor < MaskedHandle & dynamicprops function set.currentSpeedRegulation(motor, currentSpeedRegulation) if ~isBool(currentSpeedRegulation) - error('Motor::set.currentSpeedRegulation: Given parameter is not a bool.'); + error('Given parameter is not a bool.'); end currentSpeedRegulation = str2bool(currentSpeedRegulation); @@ -659,10 +642,10 @@ classdef Motor < MaskedHandle & dynamicprops function set.smoothStart(motor, steps) if ~isnumeric(steps) - error('Motor::set.smoothStart: Given parameter is not a numeric.'); + error('Given parameter is not a numeric.'); elseif steps<0 - warning('Motor::set.smoothStart: Smooth start steps have to be positive.'); - error('Motor::set.smoothStart: Smooth start steps are out of bounds.'); + warning('Smooth start steps have to be positive.'); + error('Smooth start steps are out of bounds.'); end motor.smoothStart = steps; @@ -670,10 +653,10 @@ classdef Motor < MaskedHandle & dynamicprops function set.smoothStop(motor, steps) if ~isnumeric(steps) - error('Motor::set.smoothStop: Given parameter is not a numeric.'); + error('Given parameter is not a numeric.'); elseif steps<0 - warning('Motor::set.smoothStop: Smooth stop steps have to be positive.'); - error('Motor::set.smoothStop: Smooth stop steps are out of bounds.'); + warning('Smooth stop steps have to be positive.'); + error('Smooth stop steps are out of bounds.'); end motor.smoothStop = steps; @@ -682,7 +665,7 @@ classdef Motor < MaskedHandle & dynamicprops function set.brakeMode(motor, brakeMode) if ~ischar(brakeMode) || ... (~strcmpi(brakeMode, 'coast') && ~strcmpi(brakeMode, 'brake')) - error('Motor::set.brakeMode: Given parameter is not a valid brake mode.'); + error('Given parameter is not a valid brake mode.'); end % If new brakeMode is 'Brake': reset internal tachocount once @@ -701,7 +684,7 @@ classdef Motor < MaskedHandle & dynamicprops function set.limitMode(motor, limitMode) if ~ischar(limitMode) || ... (~strcmpi(limitMode, 'tacho') && ~strcmpi(limitMode, 'time')) - error('Motor::set.limitMode: Given parameter is not a valid limit mode.'); + error('Given parameter is not a valid limit mode.'); end motor.limitMode = limitMode; @@ -709,10 +692,10 @@ classdef Motor < MaskedHandle & dynamicprops function set.limitValue(motor, limitValue) if ~isnumeric(limitValue) - error('Motor::set.limitValue: Given parameter is not a numeric.'); + error('Given parameter is not a numeric.'); elseif limitValue<0 - warning('Motor::set.limitValue: limitValue has to be positive!'); - error('Motor::set.limitValue: Given limitValue is out of bounds.'); + warning('limitValue has to be positive!'); + error('Given limitValue is out of bounds.'); end if limitValue == 0 @@ -733,13 +716,13 @@ classdef Motor < MaskedHandle & dynamicprops try motor.port = str2PortParam(class(motor), port); catch ME - error('Motor::set.port: Given parameter is not valid port string.'); + error('Given parameter is not valid port string.'); end end function set.commInterface(motor, comm) if ~isCommInterfaceValid(comm) - error('Motor::set.commInterface: Handle to commInterface not valid.'); + error('Handle to commInterface not valid.'); end motor.commInterface = comm; @@ -747,7 +730,7 @@ classdef Motor < MaskedHandle & dynamicprops function set.debug(motor, debug) if ~isBool(debug) - error('Motor::set.debug: Given parameter is not a bool.'); + error('Given parameter is not a bool.'); end motor.debug = str2bool(debug); @@ -846,7 +829,7 @@ classdef Motor < MaskedHandle & dynamicprops if motor.connectedToBrick cnt = motor.getTachoCount(); if isnan(cnt) - warning('Motor::get.tachoCount: Could not detect motor at port %s.', ... + warning('Could not detect motor at port %s.', ... port2str('Motor', motor.port)); cnt = 0; end @@ -858,7 +841,7 @@ classdef Motor < MaskedHandle & dynamicprops if motor.connectedToBrick cnt = motor.getInternalTachoCount(); if isnan(cnt) - warning('Motor::get.internalTachoCount: Could not detect motor at port %s.', ... + warning('Could not detect motor at port %s.', ... port2str('Motor', motor.port)); cnt = 0; end @@ -870,7 +853,7 @@ classdef Motor < MaskedHandle & dynamicprops if motor.connectedToBrick speed = motor.getSpeed(); if isnan(speed) - warning('Motor::get.currentSpeed: Could not detect motor at port %s.', ... + warning('Could not detect motor at port %s.', ... port2str('Motor', motor.port)); speed = 0; end @@ -917,13 +900,21 @@ 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.connectedToBrick + msg = ['Not connected to physical brick. ',... + 'You have to call connect(...) on the EV3 object first!']; + id = [ID(), ':', 'NotConnected']; + + throw(MException(id, msg)); + end + if motor.debug fprintf('(DEBUG) Sending %s\n', func2str(commandHandle)); end @@ -932,7 +923,21 @@ classdef Motor < MaskedHandle & dynamicprops % 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{:}); + try + [varargout{1:nOut}] = commandHandle(motor.commInterface, varargin{:}); + catch ME + %motor.ev3Handle.detectedCommError(ME.identifier, ME.message); + if ~isempty(strfind(ME.identifier, 'CommError')) + warning('Lost connection to the Brick!'); + motor.disconnect(); + else + warning('Something went wrong. Trying to reset the connection...'); + motor.disconnect(); + motor.connect(); + end + + throw(exception); + end end function success = setPower(motor, power) @@ -963,29 +968,17 @@ classdef Motor < MaskedHandle & dynamicprops end function [type,mode] = getTypeMode(motor) - if ~motor.connectedToBrick - error('Motor::getTypeMode: Motor-Object not connected to comm handle.'); - end - [typeNo, modeNo] = motor.handleCommand(@inputDeviceGetTypeMode, 0, motor.portInput); type = DeviceType(typeNo); mode = DeviceMode(type,modeNo); end function status = getStatus(motor) - if ~motor.connectedToBrick - error('Motor::getStatus: Motor-Object not connected to comm handle.'); - end - statusNo = motor.handleCommand(@inputDeviceGetConnection, 0, motor.portInput); status = ConnectionType(statusNo); end function cnt = getTachoCount(motor) - if ~motor.connectedToBrick - error('Motor::getTachoCount: Motor-Object not connected to comm handle.'); - end - cnt = motor.handleCommand(@outputGetCount, 0, motor.portNo); end @@ -994,10 +987,6 @@ classdef Motor < MaskedHandle & dynamicprops end function speed = getSpeed(motor) - if ~motor.connectedToBrick - error('Motor::getSpeed: Motor-Object not connected to comm handle.'); - end - speed = motor.handleCommand(@inputReadSI, 0, motor.portInput, DeviceMode.Motor.Speed); end @@ -1009,22 +998,15 @@ classdef Motor < MaskedHandle & dynamicprops % called immediately after starting the motor. % * Busy is set to true if motor is running with tacholimit or synced % - - if ~motor.connectedToBrick - error('Motor::getBusyFlag: Motor-Object not connected to comm handle.'); - end - busy = motor.handleCommand(@outputTest, 0, motor.port); end function applyBrake(motor) - if ~motor.connectedToBrick - error('Motor::applyBrake: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected - error('Motor::applyBrake: No physical motor connected to Port %s',... + if ~motor.physicalMotorConnected + error('Could not detect motor at Port %s',... port2str('Motor', motor.port)); elseif motor.currentSpeed~=0 - error('Motor::applyBrake: Can''t apply brake because Motor is moving'); + error('Can''t apply brake because Motor is moving'); end if motor.speedRegulation @@ -1037,13 +1019,11 @@ classdef Motor < MaskedHandle & dynamicprops end function releaseBrake(motor) - if ~motor.connectedToBrick - error('Motor::releaseBrake: Motor-Object not connected to comm handle.'); - elseif ~motor.physicalMotorConnected - error('Motor::releaseBrake: No physical motor connected to Port %s',... + if ~motor.physicalMotorConnected + error('Could not detect motor at Port %s',... port2str('Motor', motor.port)); elseif motor.currentSpeed~=0 - error('Motor::releaseBrake: Can''t release brake because Motor is moving'); + error('Can''t release brake because Motor is moving'); end if motor.speedRegulation @@ -1088,7 +1068,7 @@ classdef Motor < MaskedHandle & dynamicprops meta.Hidden = true; meta.Access = 'private'; elseif ~override - error('Motor::addProperty: Motor already has this property.'); + error('Motor already has this property.'); end motor.(propName) = propValue; @@ -1111,15 +1091,15 @@ classdef Motor < MaskedHandle & dynamicprops if motor.connectedToBrick if isCommInterfaceValid(motor.commInterface) - error('Motor::connect: Motor-Object already has a comm handle.'); + error('Motor-Object already has a comm handle.'); else - warning(['Motor::connect: Motor.connectedToBrick is set to ''True'', but ',... + warning(['Motor.connectedToBrick is set to ''True'', but ',... 'comm handle is invalid. Deleting invalid handle and ' ,... 'resetting Motor.connectedToBrick now...']); motor.disconnect(); - error('Motor::connect: Disconnected due to internal error.'); + error('Disconnected due to internal error.'); end end diff --git a/source/Sensor.m b/source/Sensor.m index 5e1c82947200b6c20cc13ebb9233d583be3111d1..ffdb7aca409ae40bc95f8b73b92357a23a82aa49 100644 --- a/source/Sensor.m +++ b/source/Sensor.m @@ -243,14 +243,12 @@ classdef Sensor < MaskedHandle % * This clears ALL the sensors right now, no other Op-Code available... :( % - if ~sensor.connectedToBrick - error('Sensor::reset: Sensor-Object not connected to comm handle.'); - elseif ~sensor.physicalSensorConnected - error('Sensor::reset: No physical sensor connected to Port %d.',... + if ~sensor.physicalSensorConnected + error('Could not detect sensor at Port %d',... sensor.port+1); end -% warning(['Sensor::reset: Current version of reset resets ALL devices, that is, ',... +% warning(['Current version of reset resets ALL devices, that is, ',... % 'all motor tacho counts and all other sensor counters!']); sensor.handleCommand(@inputDeviceClrAll, 0); end @@ -264,7 +262,7 @@ classdef Sensor < MaskedHandle type = sensor.type; if ~isModeValid(mode, type) - error('Sensor::set.mode: Invalid sensor mode.'); + error('Invalid sensor mode.'); else sensor.mode = mode; @@ -281,7 +279,7 @@ classdef Sensor < MaskedHandle function set.debug(sensor, debug) % Check if debug is valid and set sensor.debug if it is. if ~isBool(debug) - error('Sensor::set.debug: Given parameter is not a bool.'); + error('Given parameter is not a bool.'); end sensor.debug = str2bool(debug); @@ -289,7 +287,7 @@ classdef Sensor < MaskedHandle function set.port(sensor, port) if ~isPortStrValid(class(sensor),port) - error('Sensor::set.port: Given port is not a valid port.'); + error('Given port is not a valid port.'); else sensor.port = str2PortParam(class(sensor), port); end @@ -297,7 +295,7 @@ classdef Sensor < MaskedHandle function set.commInterface(sensor, comm) if ~isCommInterfaceValid(comm) - error('Sensor::set.commInterface: Handle to commInterface not valid.'); + error('Handle to commInterface not valid.'); else sensor.commInterface = comm; end @@ -354,7 +352,7 @@ classdef Sensor < MaskedHandle if sensor.connectedToBrick value = sensor.getValue(defaultMode); if isnan(value) - warning('Sensor::get.value: Could not detect sensor at port %d.', ... + warning('Could not detect sensor at port %d.', ... sensor.port+1); value = 0; end @@ -383,10 +381,8 @@ classdef Sensor < MaskedHandle methods (Access = private) % Private brick functions that are wrapped by dependent params function setMode(sensor, mode) - if ~sensor.connectedToBrick - error('Sensor::getTachoCount: Sensor-Object not connected to comm handle.'); - elseif ~sensor.physicalSensorConnected - error('Sensor::getTachoCount: No physical sensor connected to Port %d',... + if ~sensor.physicalSensorConnected + error('Could not detect sensor at Port %d',... sensor.port+1); end @@ -407,16 +403,12 @@ classdef Sensor < MaskedHandle % 5 is numerically highest available number of modes for a sensor(NXT Color) if ~isnumeric(defaultMode) || defaultMode > 5 - error('Sensor::getValue: Invalid mode'); + error('Invalid mode'); end else defaultMode = -1; end - if ~sensor.connectedToBrick - error('Sensor::getValue: Sensor-Object not connected to comm handle.'); - end - if defaultMode ~= -1 mode = defaultMode; else @@ -439,19 +431,11 @@ classdef Sensor < MaskedHandle end function status = getStatus(sensor) - if ~sensor.connectedToBrick - error('Sensor::getStatus: Sensor-Object not connected to comm handle.'); - end - statusNo = sensor.handleCommand(@inputDeviceGetConnection, 0, sensor.port); status = ConnectionType(statusNo); end function [type,mode] = getTypeMode(sensor) - if ~sensor.connectedToBrick - error('Sensor::getTypeMode: Sensor-Object not connected to comm handle.'); - end - type = DeviceType.Error; for i = 1:10 @@ -471,15 +455,20 @@ classdef Sensor < MaskedHandle end end - end - - methods (Access = private) - function varargout = handleCommand(sensor, commandHandle, varargin) + 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.connectedToBrick + msg = ['Not connected to physical brick. ',... + 'You have to call connect(...) on the EV3 object first!']; + id = [ID(), ':', 'NotConnected']; + + throw(MException(id, msg)); + end + if sensor.debug fprintf('(DEBUG) Sending %s\n', func2str(commandHandle)); end @@ -488,7 +477,21 @@ classdef Sensor < MaskedHandle % 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{:}); + try + [varargout{1:nOut}] = commandHandle(sensor.commInterface, varargin{:}); + catch ME + %sensor.ev3Handle.detectedCommError(ME.identifier, ME.message); + if ~isempty(strfind(ME.identifier, 'CommError')) + warning('Lost connection to the Brick!'); + sensor.disconnect(); + else + warning('Something went wrong. Trying to reset the connection...'); + sensor.disconnect(); + sensor.connect(); + end + + throw(exception); + end end end @@ -498,16 +501,16 @@ classdef Sensor < MaskedHandle if sensor.connectedToBrick if isCommInterfaceValid(sensor.commInterface) - error('Sensor::connect: Sensor-Object already has a comm handle.'); + error('Sensor-Object already has a comm handle.'); else - warning(['Sensor::connect: Sensor.connectedToBrick is set to ''True'', but ',... + warning(['Sensor.connectedToBrick is set to ''True'', but ',... 'comm handle is invalid. Deleting invalid handle and ' ,... 'resetting Sensor.connectedToBrick now...']); sensor.commInterface = 0; sensor.connectedToBrick = false; - error('Sensor::connect: Disconnected due to internal error.'); + error('Disconnected due to internal error.'); end end