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

Visualize science data as points #88

Merged
merged 32 commits into from
Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1b1a44c
Migrate to Ignition Garden
chapulina Dec 6, 2021
1b1c856
nightlies
chapulina Dec 6, 2021
4e110ea
Remove all performance tricks, use points, increase camera clip dista…
chapulina Nov 20, 2021
36eea70
grids
chapulina Dec 8, 2021
eafd631
Merge branch 'main' into chapulina/garden
chapulina Dec 8, 2021
ac8141a
fix Dockerfiles
chapulina Dec 8, 2021
e31f2cb
Merge branch 'chapulina/garden' into chapulina/marker_debug
chapulina Dec 8, 2021
6152852
clip
chapulina Dec 8, 2021
0db3884
add plane
chapulina Dec 8, 2021
794bf8f
Merge branch 'main' into chapulina/garden
chapulina Dec 8, 2021
bfa4da7
Disable mission tests until upstream is using Garden
chapulina Dec 8, 2021
98e2111
Increase depth tolerance on spawn test
chapulina Dec 8, 2021
3af16d0
use garden image and re-enable tests
chapulina Dec 9, 2021
7867b8a
merged from chapulina/garden
chapulina Dec 9, 2021
b8db4d8
YoYo debug
chapulina Dec 9, 2021
b2335bf
Merge branch 'main' into chapulina/garden
chapulina Dec 14, 2021
5c30270
merged from main
chapulina Dec 14, 2021
930cb8c
merged from main
chapulina Dec 15, 2021
801f19f
Merge branch 'chapulina/garden' into chapulina/marker_debug
chapulina Dec 15, 2021
d72522d
Merge branch 'main' into chapulina/garden
chapulina Dec 15, 2021
d12c457
merged from main
chapulina Dec 15, 2021
5229149
merged from main
chapulina Dec 18, 2021
6f92329
tweaks
chapulina Dec 21, 2021
704a289
Grid: modify default grid and add GUI plugin
chapulina Dec 21, 2021
fa28e23
merged from chapulina/grid
chapulina Dec 21, 2021
def309b
merged from main
chapulina Dec 22, 2021
c77869c
Fix test segfaults - but why are they happening on this branch?!
chapulina Dec 22, 2021
1e6697d
Remove miniature scale from science data and fix segfault
chapulina Dec 22, 2021
603c4bf
merged from chapulina/barycentric_segfault
chapulina Dec 22, 2021
8f3b477
UX
chapulina Dec 22, 2021
5d6f0ab
merged from main
chapulina Dec 23, 2021
4d79b2a
cleanup bad merge and revert data removal
chapulina Dec 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions lrauv_ignition_plugins/src/ScienceSensorsSystem.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,6 @@ class tethys::ScienceSensorsSystemPrivate

/// \brief Publish a few more times for visualization plugin to get them
public: int repeatPubTimes = 1;

// TODO This is a workaround pending upstream Marker performance improvements.
// \brief Performance trick. Skip depths below this z, so have memory to
// visualize higher layers at higher resolution.
// This is only for visualization, so that MAX_PTS_VIS can calculate close
// to the actual number of points visualized.
// Sensors shouldn't use this.
public: const float SKIP_Z_BELOW = -20;
};

/////////////////////////////////////////////////
Expand Down Expand Up @@ -541,12 +533,6 @@ void ScienceSensorsSystemPrivate::ReadData(
// Check validity of spatial coordinates
if (!std::isnan(latitude) && !std::isnan(longitude) && !std::isnan(depth))
{
// Performance trick. Skip points below a certain depth
if (-depth < this->SKIP_Z_BELOW)
{
continue;
}

// Convert lat / lon / elevation to Cartesian ENU
auto cart = this->world.SphericalCoordinates(_ecm).value()
.PositionTransform({IGN_DTOR(latitude), IGN_DTOR(longitude), 0.0},
Expand All @@ -555,12 +541,6 @@ void ScienceSensorsSystemPrivate::ReadData(
// Flip sign of z, because positive depth is negative z.
cart.Z() = -depth;

// Performance trick. Skip points beyond some distance from origin
if (abs(cart.X()) > 1000 || abs(cart.Y()) > 1000)
{
continue;
}

// Gather spatial coordinates, 3 fields in the line, into point cloud
// for indexing this time slice of data.
this->timeSpaceCoords[lineTimeIdx]->push_back(
Expand Down
140 changes: 45 additions & 95 deletions lrauv_ignition_plugins/src/VisualizePointCloud.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,6 @@ namespace tethys
/// \brief Message holding a float vector.
public: ignition::msgs::Float_V floatVMsg;

/// \brief Performance trick. Cap number of points to visualize, to save
/// memory.
public: const int MAX_PTS_VIS = 1000;

/// \brief Performance trick. Render only every other n. Increase to render
/// fewer markers (faster performance). Recalulated in function.
public: int renderEvery = 1;

/// \brief Minimum value in latest float vector
public: float minFloatV{std::numeric_limits<float>::max()};

Expand All @@ -96,6 +88,9 @@ namespace tethys
/// \brief Color for maximum value
public: ignition::math::Color maxColor{0, 255, 0, 255};

/// \brief Size of each point
public: float pointSize{20};

/// \brief True if showing
public: bool showing{true};
};
Expand Down Expand Up @@ -305,6 +300,10 @@ void VisualizePointCloud::OnFloatV(const ignition::msgs::Float_V &_msg)
this->SetMaxFloatV(data);
}

// TODO(chapulina) Publishing whenever we get a new point cloud and a new
// floatV is good in case these topics are out of sync. But here they're
// synchronized, so in practice we're publishing markers twice for each
// PC+float that we get.
this->PublishMarkers();
}

Expand Down Expand Up @@ -349,40 +348,29 @@ void VisualizePointCloud::PublishMarkers()
}

std::lock_guard<std::recursive_mutex>(this->dataPtr->mutex);
ignition::msgs::Marker marker;
marker.set_ns(this->dataPtr->pointCloudTopic + this->dataPtr->floatVTopic);
marker.set_id(1);
marker.set_action(ignition::msgs::Marker::ADD_MODIFY);
marker.set_type(ignition::msgs::Marker::POINTS);
marker.set_visibility(ignition::msgs::Marker::GUI);

// Used to calculate cap of number of points to visualize, to save memory
int nPts = this->dataPtr->pointCloudMsg.height() *
this->dataPtr->pointCloudMsg.width();
// If there are more points than we can render, render every n
if (nPts > this->dataPtr->MAX_PTS_VIS)
{
this->dataPtr->renderEvery = (int) round(
nPts / (double) this->dataPtr->MAX_PTS_VIS);
ignwarn << "Only rendering one science data point for each "
<< this->dataPtr->renderEvery << std::endl;
}

ignition::msgs::Marker_V markers;
ignition::msgs::Set(marker.mutable_scale(),
ignition::math::Vector3d::One * this->dataPtr->pointSize);

PointCloudPackedIterator<float> iterX(this->dataPtr->pointCloudMsg, "x");
PointCloudPackedIterator<float> iterY(this->dataPtr->pointCloudMsg, "y");
PointCloudPackedIterator<float> iterZ(this->dataPtr->pointCloudMsg, "z");

// Index of point in point cloud, visualized or not
int ptIdx{0};
// Number of points actually visualized
int nPtsViz{0};
auto minC = this->dataPtr->minColor;
auto maxC = this->dataPtr->maxColor;
auto floatRange = this->dataPtr->maxFloatV - this->dataPtr->minFloatV;
for (;iterX != iterX.end() &&
iterY != iterY.end() &&
iterZ != iterZ.end(); ++iterX, ++iterY, ++iterZ, ++ptIdx)
{
// Performance trick. Only publish every nth. Skip z below some depth
if (this->dataPtr->renderEvery == 0 ||
ptIdx % this->dataPtr->renderEvery != 0)
{
continue;
}

// Value from float vector, if available. Otherwise publish all data as
// zeroes.
float dataVal = 0.0;
Expand All @@ -391,82 +379,30 @@ void VisualizePointCloud::PublishMarkers()
dataVal = this->dataPtr->floatVMsg.data(ptIdx);
}

mabelzhang marked this conversation as resolved.
Show resolved Hide resolved
auto msg = markers.add_marker();

msg->set_ns(this->dataPtr->pointCloudTopic + this->dataPtr->floatVTopic);
msg->set_id(ptIdx + 1);

// Don't visualize NaN
if (std::isnan(dataVal))
{
msg->set_action(ignition::msgs::Marker::DELETE_MARKER);
continue;
}
msg->set_action(ignition::msgs::Marker::ADD_MODIFY);

auto ratio = (dataVal - this->dataPtr->minFloatV) /
(this->dataPtr->maxFloatV - this->dataPtr->minFloatV);
auto color = this->dataPtr->minColor +
(this->dataPtr->maxColor - this->dataPtr->minColor) * ratio;

ignition::msgs::Set(msg->mutable_material()->mutable_ambient(), color);
ignition::msgs::Set(msg->mutable_material()->mutable_diffuse(), color);
msg->mutable_material()->mutable_diffuse()->set_a(0.5);
auto ratio = floatRange > 0 ?
(dataVal - this->dataPtr->minFloatV) / floatRange : 0.0f;
ignition:: math::Color color{
minC.R() + (maxC.R() - minC.R()) * ratio,
minC.G() + (maxC.G() - minC.G()) * ratio,
minC.B() + (maxC.B() - minC.B()) * ratio
};

// TODO: Use POINTS or LINE_LIST, but need per-vertex color
msg->set_type(ignition::msgs::Marker::BOX);
msg->set_visibility(ignition::msgs::Marker::GUI);
ignition::msgs::Set(msg->mutable_scale(),
ignition::math::Vector3d(0.2, 0.2, 0.2));
ignition::msgs::Set(marker.add_materials()->mutable_diffuse(), color);

ignition::msgs::Set(msg->mutable_pose(), ignition::math::Pose3d(
ignition::msgs::Set(marker.add_point(), ignition::math::Vector3d(
*iterX,
*iterY,
*iterZ,
0, 0, 0));

/*
// Use POINTS type and array for better performance, pending per-point
// color.
// One marker per point cloud, many points.
// TODO Implement in ign-gazebo per-point color like RViz point arrays,
// so can have just 1 marker, many points in it, each with a specified
// color, to improve performance. Color is the limiting factor that
// requires us to use many markers here, 1 point per marker.
// https://github.com/osrf/lrauv/issues/52
ignition::msgs::Set(msg->mutable_pose(), ignition::math::Pose3d(
0, 0, 0, 0, 0, 0));
auto pt = msg->add_point();
pt->set_x(*iterX);
pt->set_y(*iterY);
pt->set_z(*iterZ);
*/

if (nPtsViz < 10)
{
igndbg << "Added point " << nPtsViz << " at "
<< msg->pose().position().x() << ", "
<< msg->pose().position().y() << ", "
<< msg->pose().position().z() << ", "
<< "value " << dataVal << ", "
<< std::endl;
}
++nPtsViz;
*iterZ));
}

igndbg << "Received [" << nPts
<< "] markers, visualizing [" << nPtsViz << "]"
<< std::endl;

ignition::msgs::Boolean res;
bool result;
unsigned int timeout = 5000;
this->dataPtr->node.Request("/marker_array", markers, timeout, res, result);
igndbg << "Visualizing " << marker.point_size() << " points"
<< std::endl;

if (!result || !res.data())
{
ignerr << "Failed to create markers on /marker_array" << std::endl;
}
this->dataPtr->node.Request("/marker", marker);
}

//////////////////////////////////////////////////
Expand Down Expand Up @@ -542,6 +478,20 @@ void VisualizePointCloud::SetMaxFloatV(float _maxFloatV)
this->MaxFloatVChanged();
}

/////////////////////////////////////////////////
float VisualizePointCloud::PointSize() const
{
return this->dataPtr->pointSize;
}

/////////////////////////////////////////////////
void VisualizePointCloud::SetPointSize(float _pointSize)
{
this->dataPtr->pointSize = _pointSize;
this->PointSizeChanged();
this->PublishMarkers();
}

// Register this plugin
IGNITION_ADD_PLUGIN(tethys::VisualizePointCloud,
ignition::gui::Plugin)
19 changes: 19 additions & 0 deletions lrauv_ignition_plugins/src/VisualizePointCloud.hh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ namespace tethys
NOTIFY MaxFloatVChanged
)

/// \brief Point size
Q_PROPERTY(
float pointSize
READ PointSize
WRITE SetPointSize
NOTIFY PointSizeChanged
)

/// \brief Constructor
public: VisualizePointCloud();

Expand Down Expand Up @@ -196,6 +204,17 @@ namespace tethys
/// \brief Notify that maximum value has changed
signals: void MaxFloatVChanged();

/// \brief Get the point size
/// \return Maximum value
public: Q_INVOKABLE float PointSize() const;

/// \brief Set the point size
/// \param[ax] _pointSize Maximum value.
public: Q_INVOKABLE void SetPointSize(float _pointSize);

/// \brief Notify that point size has changed
signals: void PointSizeChanged();

/// \brief Set whether to show the point cloud.
/// \param[in] _show Boolean value for displaying the points.
public: Q_INVOKABLE void Show(bool _show);
Expand Down
36 changes: 29 additions & 7 deletions lrauv_ignition_plugins/src/VisualizePointCloud.qml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ import "qrc:/qml"
ColumnLayout {
spacing: 10
Layout.minimumWidth: 350
Layout.minimumHeight: 300
Layout.minimumHeight: 350
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10

function isUniform() {
return VisualizePointCloud.minFloatV >= VisualizePointCloud.maxFloatV
}

RowLayout {
spacing: 10
Layout.fillWidth: true
Expand Down Expand Up @@ -110,7 +114,23 @@ ColumnLayout {
}
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: qsTr("Ignition transport topics publishing FloatV messages")
ToolTip.text: qsTr("Ignition transport topics publishing FloatV messages, used to color each point on the cloud")
}

Label {
Layout.columnSpan: 1
text: "Point size"
}

IgnSpinBox {
id: pointSizeSpin
value: VisualizePointCloud.pointSize
minimumValue: 1
maximumValue: 1000
decimals: 0
onEditingFinished: {
VisualizePointCloud.SetPointSize(pointSizeSpin.value)
}
}
}

Expand All @@ -120,20 +140,20 @@ ColumnLayout {

Label {
Layout.columnSpan: 1
text: "Min"
text: isUniform() ? "Color" : "Min"
}

Label {
Layout.columnSpan: 1
Layout.maximumWidth: 50
text: VisualizePointCloud.minFloatV.toFixed(2)
text: VisualizePointCloud.minFloatV.toFixed(4)
elide: Text.ElideRight
visible: !isUniform()
}

Button {
Layout.columnSpan: 1
id: minColorButton
Layout.fillWidth: true
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: qsTr("Color for minimum value")
Expand Down Expand Up @@ -163,7 +183,7 @@ ColumnLayout {
Button {
Layout.columnSpan: 1
id: maxColorButton
Layout.fillWidth: true
visible: !isUniform()
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: qsTr("Color for maximum value")
Expand Down Expand Up @@ -193,13 +213,15 @@ ColumnLayout {
Label {
Layout.columnSpan: 1
Layout.maximumWidth: 50
text: VisualizePointCloud.maxFloatV.toFixed(2)
text: VisualizePointCloud.maxFloatV.toFixed(4)
elide: Text.ElideRight
visible: !isUniform()
}

Label {
Layout.columnSpan: 1
text: "Max"
visible: !isUniform()
}
}

Expand Down