Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Convert RealSense2 options to MetriCam2 parameter #47

Merged
merged 34 commits into from
Jan 17, 2018

Conversation

jangernert
Copy link
Collaborator

@jangernert jangernert commented Dec 21, 2017

WORK IN PROGRESS!

This pull request was opened to get some early feedback while working on the changes.

@f00f:
As you can see each option can be set for each sensor in the camera. This doesn't mean the option is supported by all sensors, just that the API allows it. Currently there are 2 sensors in the camera samples we got (named RGB and Stereo). Should we hide this implementation detail in the camera implementation?

My idea is to check which option is supported by which sensor and if it makes sense to have it for that sensor. If just one of the sensor support it have just one parameter and implicitly set the desired sensor. If the option works with both sensors implement two parameter named something like Option27Color and Option27Stereo.

Another thing is: the API uses float values for all options. IMO it is nicer to have types that make sense for the specific option. For example an option that can be either turned off or on should be boolean and internally we use the float values 1 and 0.

@jangernert jangernert self-assigned this Dec 21, 2017
@jangernert jangernert requested a review from f00f December 21, 2017 12:12
@jangernert
Copy link
Collaborator Author

jangernert commented Dec 21, 2017

@f00f
Librealsense2 provides the settings EXPOSURE, ENABLE_AUTO_EXPOSURE and AUTO_EXPOSURE_MODE. So you can enable auto exposure and on top of that specify one of three auto exposure modes (Static, Anti-Flicker and Hybrid). So the question is now how to expose the property.
My first idea was to have an AutoExposure(Color/Depth) property that takes an enum with the specified mode and enables auto exposure as well. But it turns out the camera I'm using to test everything on (D435) does not support AUTO_EXPOSURE_MODE but does support ENABLE_AUTO_EXPOSURE.
So currently I only provide a property to enable/disable auto exposure and ignore the mode setting that could work with other cameras (don't know). What do you think would be the best solution here?

edit: Simon says (pun intended) the other intel cameras also don't support the AUTO_EXPOSURE_MODE and there aren't any switches in the intel tool for it either. So I'm just gonna omit it.

@jangernert
Copy link
Collaborator Author

jangernert commented Dec 21, 2017

All compatible options of the D435 have been turned into properties.
Still needs some testing and a review by @f00f

TODO for 2018:

  • Test all Properties with D435
  • Test all properties with D415
  • Remove methods to mess with realsense options directly
  • Don't expose RealSense2API anymore
  • Write summary comments for tool tips

@jangernert
Copy link
Collaborator Author

jangernert commented Dec 22, 2017

@f00f :
I noticed parameter with a RangeParamDesc accept values even outside the specified range just fine. Should the camera implementation itself check if the value is valid or is there a layer of MetriCam2 that should catch the mistake?

@jangernert
Copy link
Collaborator Author

@f00f review please =)

@f00f
Copy link
Contributor

f00f commented Jan 12, 2018

I'll try to address your questions/remarks in the order of appearance

  • Multiple sensors which might support the same parameter:
  • I agree that our interface should use typed parameters
  • AUTO_EXPOSURE_MODE: agree, ditch it. We can always care for it later, if needed.
  • RangeParamDesc: we have talked about that. So far no checks are done (in MC2 in general) if the property is set directly. You addressed that [Proposal] Rework Camera Properties #49

Now, I'll have a look at the code...

@f00f
Copy link
Contributor

f00f commented Jan 16, 2018

Just a note: the last three commits are off-topic.
They further delay this review which is already taking way too long.

@jangernert
Copy link
Collaborator Author

@mischastik needs the stereo calibration tool to work with realsense2 devices. These changes were necessary to make the application work. I just wanted to squeeze them in as fast as possible :D

Copy link
Contributor

@f00f f00f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of my comments apply to multiple code sections, in most cases I have not repeatet them.

In addition to the comments I'd prefer it if more specific Exception types were used.

HandleError(error);
return height;
}
catch (Exception)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the use of this try-catch-throw construct? Should be the same without it.

@@ -651,6 +731,21 @@ public RS2Frame(IntPtr p)
public bool IsValid() => (null != Handle);
}

public struct RS2StreamProfileList
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would name it RS2StreamProfilesList, like the underlying API function.

@@ -104,6 +105,9 @@ public Camera Camera
// use cam.Channels;
// Update child controls.
InitConfigurationParameters(cam);

cam.OnConnected += (camera) => { InitConfigurationParameters(camera); };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you attach event handlers you have to detach them as well.
At the beginning of this setter check for cam != null and then detach the handlers.
Otherwise you could get UI updates of the old camera after assigning a new one (rare case, but costs a day to debug).

string parameterName = scrollbarValue.Name.Replace(VALUE_SUFFIX, string.Empty);
Dictionary<string, object> keyValues = new Dictionary<string, object>();
keyValues.Add(parameterName, parameterValue);
Camera.SetParameters(keyValues);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use Camera.SetParameter(paramDesc.Name, parameterValue) you don't need the Dictionary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the parameter is not writable in the current connection state? Just curious.

string parameterName = upDownValue.Name.Replace(VALUE_SUFFIX, string.Empty);
Dictionary<string, object> keyValues = new Dictionary<string, object>();
keyValues.Add(parameterName, parameterValue);
Camera.SetParameters(keyValues);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with slider

get
{
ParamDesc<bool> res = new ParamDesc<bool>();
res.Description = "Enable / disable trigger to be outputed from the camera to any external device on every depth frame";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Enable / disable output trigger on every depth frame"

bool haveRight = false;

while (true)
while(_updatingPipeline)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Busy waiting feels dirty.
Wouldn't this be nicer with a ManualResetEvent? I don't know how fast it is to check that, though.

break;
}
}
catch (Exception)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why catch/throw?

Point2i resolution = RealSense2API.GetStreamProfileResolution(p);
if (resolution == refResolution)
{
profile = p;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could return p; here and get rid of the profile variable

if (adjusted)
throw new Exception(string.Format("Value {0} for '{1}' is outside of the range between {2} and {3}", value, desc.Name, desc.Min, desc.Max));
else
throw new Exception(string.Format("Value {0} (adjusted to {1} to match stepsize) for 'LaserPower' is outside of the range between {2} and {3}", value, adjustedValue, desc.Min, desc.Max));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded string "LaserPower" looks wrong, should use desc.Name

Copy link
Contributor

@f00f f00f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open issues from last review:

  1. In addition to the comments I'd prefer it if more specific Exception types were used.
  2. What happens if someone sets ColorResolution while the pipeline is stopped?
  3. resolution -> Point2i conversion method not used in Camera. I'd make the resolution -> Point2i conversion a static method of a helper class.

Dictionary<string, object> keyValues = new Dictionary<string, object>();
keyValues.Add(parameterName, parameterValue);
Camera.SetParameters(keyValues);
string parameterName = paramDesc.Name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable parameterName

@@ -647,5 +644,11 @@ private TextBox CreateTextBox(Camera.ParamDesc paramDesc, int currentRow)
return textBoxValue;
}
#endregion

private Point2i StringToPoint2i(string s)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd name it ResolutionToPoint2i to clarify that it's different from Point2i.Parse

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed. I'll move it to the Conversions helper class in the Attributes-branch. Moving all this code around seems off topic here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I just wanted to squeeze them in as fast as possible :D

return true;

return false;
return RealSense2API.GetOption(_pipeline, RealSense2API.SensorName.COLOR, RealSense2API.Option.BACKLIGHT_COMPENSATION) == 1.0f ? true : false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ? true : false is not needed.

If you want to write it in one line I would reverse the order of the comparison to make clear what the return value is compared against. As it is the line is too long to be displayed in Github CR.

if (adjusted_value < min)
adjusted_value += step;

float adjusted_value = AdjustValue(option.min, option.max, value, option.step);
CheckRangeValid<int>(WhiteBalanceDesc, value, (int)adjusted_value, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use the option object in the CheckRangeValid method (since you have it already).
Using the ParamDesc here repeats the QueryOption call and adds no value, but only delay.

out string desc);

res = new RangeParamDesc<int>((int)min, (int)max);
var option = QueryOption(RealSense2API.Option.FRAMES_QUEUE_SIZE, RealSense2API.SensorName.COLOR);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would even write a method which contains these two lines, QueryOption and new RangeParamDesc, just because I wouldn't want to write it over and over again (but it's there already, so you may as well keep it).

@jangernert
Copy link
Collaborator Author

@f00f I think everything is addressed

@f00f f00f merged commit e7756d9 into master Jan 17, 2018
@f00f f00f deleted the realsense2_options_to_metricam_parameter branch January 17, 2018 14:47
@sisiplac
Copy link
Contributor

sisiplac commented Feb 8, 2018

There was one bug introduced by this pull request. Setting the LaserMode accidentally sets laser power instead of "EMITTER_ENABLED".
I will fix that...

f00f pushed a commit that referenced this pull request Feb 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants