Skip to content

Commit

Permalink
Merge branch 'skybrush-io:main' into sorted-formation-objects
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-advantitge authored Sep 14, 2024
2 parents 16337b4 + 83219de commit 5456750
Show file tree
Hide file tree
Showing 30 changed files with 663 additions and 123 deletions.
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Proximity warnings are now restricted to above the minimum navigation threshold
only by default. You can switch back to the old behaviour in the safety
settings panel if needed.

- Proximity warnings can now be executed manually on all pairs of drones in the
current frame by pressing a button in the Safety panel.

## [3.4.2] - 2024-09-06

### Fixed

- Fixed a bug that was accidentally introduced in the transition calculation in
version 3.4.1.

- Duplicating a light effect now uses numeric suffixes added to the original
name, similarly to how Blender does it in its own code.

## [3.4.1] - 2024-08-26

### Changed

- Distances in the safety overlay are now shown with two decimal digits to
cater for the needs of indoor shows.

### Fixed

- The add-on is now compatible with Blender 4.2 LTS.

- The constraints on the first storyboard entry now start at an influence of
1.0 when the start of the scene coincides with the first storyboard entry
(which is the typical case). This makes it slightly harder to mess up the
takeoff procedure by moving drones around manually before the first storyboard
entry.

## [3.4.0] - 2024-08-01

### Added

- Spatial constraints on light effects can now be inverted.

- "Inside the mesh" light effects now take mesh deformations into account. This
Expand All @@ -18,6 +56,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Light effects panel now shows which effects are active in the current frame.

- Safety warning overlays now use different colors for different types of
safety warnings: red for proximity alerts (drones being too close),
yellow for velocity alerts (drones moving too fast) and blue for altitude
alerts (drones being too high or too low).

## [3.3.3] - 2024-03-19

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions doc/modules/ROOT/pages/install.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ An additional requirement is that you need to have active Internet connection on

=== 2. Install Blender

There are many Blender versions out there, we aim for compatibility with the https://www.blender.org/download/lts/[latest Long Term Support (LTS) release]. This is currently version 2.93.x.
There are many Blender versions out there, we aim for compatibility with the https://www.blender.org/download/lts/[latest Long Term Support (LTS) release]. This is version 4.2 at the time of writing. if you are unsure, check the version number of the https://www.blender.org/download/lts/[latest Long Term Support (LTS) release] on the Blender site.

=== 3. Install Skybrush Studio for Blender

Expand Down Expand Up @@ -60,7 +60,7 @@ image::install_blender_addons.jpg[Install Blender Add-ons]
NOTE: If the update still fails after following the steps outlined above, try to completely uninstall the old add-on first manually (as described below) and then re-install the new one from scratch.

== Uninstallation

If you decide to uninstall *Skybrush Studio for Blender* for any reasons, you have to do it manually. Removing the add-on from Blender's add-on manager is possible, but it will not remove all files related to *Skybrush Studio for Blender*. The full, manual process is as follows:

1. Deactivate the add-on first in Blender's add-on manager.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The checkbox at the top left corner of the panel allows you to disable the safet

This option lets you define a minimum safety distance between your drones. If there are drones at the given frame that are closer to each other than this safety distance, you get real-time proximity warnings.

By default, the proximity warning is limited to drones above the minimum navigation altitude only (see below in the section about altitude warnings). This is to prevent spurious warnings about drones being too close in the takeoff grid. You can change this in the panel by choosing between the "All drones" and "Drones abouve min altitude" setting.

The text-based proximity warning on the left side of the 3D Viewport editor always shows you the minimum distance between all drone pairs on the current frame. This drone pair is also highlighted with red, along with a red line connecting them.

To enable or disable proximity warnings, use the btn:[Show proximity warnings] checkbox.
Expand All @@ -26,17 +28,17 @@ NOTE: Distances are measured between the centers of the drones, not between thei

== Altitude warnings

This option lets you define a maximum altitude for your drone show. If there are drones above this altitude (measured along the `Z` axis), you get real-time altitude warnings.
This option lets you define a minimum and a maximum altitude for your drone show. If there are drones above the maximum altitude (measured along the `Z` axis), or drones moving _horizontally_ below the minimum altitude, you get real-time altitude warnings.

The text-based altitude warning on the left side of the 3D Viewport editor always shows you the overall altitude range of drones on the current frame. Drones above the altitude threshold at a given frame are highlighted in red.
The text-based altitude warning on the left side of the 3D Viewport editor always shows you the overall altitude range of drones on the current frame. Drones above the altitude threshold at a given frame are highlighted in yellow.

To enable or disable altitude warnings, use the btn:[Show altitude warnings] checkbox.

== Velocity warnings

This option lets you define a maximum horizontal and vertical speed for your drone show (vertical speed can be further differentiated into maximum up and down speed). If there are drones above these velocity limits, you get real-time velocity warnings.

The text-based velocity warning on the left side of the 3D Viewport editor always shows you the maximum horizontal (XY), upwards (U) and downwards (D) velocity of drones on the current frame. Drones above the velocity thresholds at a given frame are highlighted in red.
The text-based velocity warning on the left side of the 3D Viewport editor always shows you the maximum horizontal (XY), upwards (U) and downwards (D) velocity of drones on the current frame. Drones above the velocity thresholds at a given frame and drones moving horizontally below the minimum navigation altitude threshold are highlighted in blue.

To enable or disable velocity warnings, use the btn:[Show velocity warnings] checkbox.

Expand All @@ -49,6 +51,10 @@ The rules are as follows. If the cache contains information about the positions
The safest way to perform the real-time velocity validation is to start playing the show in the 3D Viewport because then Blender will visit the frames one by one. Another option is to scrub through the video by dragging the current frame marker in the Timeline panel of Blender, _slowly_. The definition of "slow" depends on the zoom level of the timeline - if the timeline is zoomed out to cover a ten-minute show, even a few pixels on the timeline may represent a jump that is large enough so that *Skybrush Studio* will not attempt an estimation.
****

== Finding all drone pairs closer than the proximity warning threshold

Real-time proximity warnings that are running during playback must be fast, therefore we cannot afford finding _all_ pairs of drones in a frame that are closer than the proximity threshold by default; only one such pair will be marked in the 3D view. However, if you see a proximity warning marker and you suspect that there might be more pairs of drones that violate the proximity threshold in the current frame, you can ask for a full, exhaustive scan of all pairs of drones by pressing the btn:[Calculate All Proximity Warnings] button. This will refresh the current frame and mark all pairs of drones that are too close to each other.

== Validating full or partial trajectories

Press the btn:[Validate Trajectories] button to execute a full validation for a frame range instead of only for a single frame. This might take some time depending on the number of drones and the number of frames selected.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "skybrush-studio-for-blender"
version = "3.3.3"
version = "3.4.2"
description = "Skybrush Studio for Blender is a professional drone show designer framework integrated into Blender"
license = "GPL-3.0-or-later"
authors = ["CollMot Robotics Ltd. <[email protected]>"]
Expand Down
4 changes: 3 additions & 1 deletion src/addons/ui_skybrush_studio.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Skybrush Studio",
"author": "CollMot Robotics Ltd.",
"description": "Extends Blender with UI components for drone show design",
"version": (3, 3, 3),
"version": (3, 4, 2),
"blender": (3, 3, 0),
"category": "Interface",
"doc_url": "https://doc.collmot.com/public/skybrush-studio-for-blender/latest/",
Expand Down Expand Up @@ -100,6 +100,7 @@
RemoveStoryboardEntryOperator,
ReorderFormationMarkersOperator,
ReturnToHomeOperator,
RunFullProximityCheckOperator,
SelectFormationOperator,
SelectStoryboardEntryForCurrentFrameOperator,
SetServerURLOperator,
Expand Down Expand Up @@ -219,6 +220,7 @@
AddMarkersFromZippedCSVOperator,
AddMarkersFromQRCodeOperator,
RefreshFileFormatsOperator,
RunFullProximityCheckOperator,
)

#: List widgets in this addon.
Expand Down
73 changes: 70 additions & 3 deletions src/modules/sbstudio/math/nearest_neighbors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Algorithm to find the nearest neighbors in a set of points."""

from numpy import array, fill_diagonal, inf, newaxis, searchsorted, sum
from numpy import array, fill_diagonal, inf, newaxis, nonzero, ptp, searchsorted, sum

__all__ = ("find_nearest_neighbors",)

Expand Down Expand Up @@ -42,6 +42,19 @@ def _nearest_neighbors_brute_force(points):
return points[first], points[second], dist_sq_matrix[first, second] ** 0.5


def _reorder_along_principal_axis(points):
"""Given a list of points, finds the principal axis along which the dataset
is the "widest" and then sorts the points in ascending order along this
axis.
Returns:
the sorted points and the index of the principal axis
"""
principal_axis = ptp(points, axis=0).argmax()
points = points[points[:, principal_axis].argsort(), :]
return points, principal_axis


def _nearest_neighbors_divide_and_conquer(points):
"""Finds the nearest neighbors in a 2D or 3D point set given as a NumPy
array (one point per row), using an O(n log(n) log(n)) divide-and-conquer
Expand All @@ -52,8 +65,7 @@ def _nearest_neighbors_divide_and_conquer(points):
return None, None, inf

# Find the principal axis along which the dataset is the "widest"
principal_axis = points.ptp(axis=0).argmax()
points = points[points[:, principal_axis].argsort(), :]
points, principal_axis = _reorder_along_principal_axis(points)
p, q, dist_sq = _nearest_neighbors_divide_and_conquer_step(points, principal_axis)
return p, q, dist_sq**0.5

Expand Down Expand Up @@ -128,9 +140,64 @@ def find_nearest_neighbors(points):
the coordinates of the first and the second point in the closest point
pair, and their distance
"""
if not points:
# we have no points
return None, None, inf

points = array(points, dtype=float)
if points.shape[0] < 2:
# we have less than two points
return None, None, inf

return _nearest_neighbors_divide_and_conquer(points)


def find_all_point_pairs_closer_than(points, threshold):
"""Finds all point pairs that are closer than the given threshold.
This is a slow brute-force algorithm, but it does not have to be executed
frequently so it is probably okay.
Parameters:
points: the input, either as a list-of-points where each point may be
a tuple or a list, or as a NumPy array where each row is a point
Returns:
the coordinate pairs representing all pairs of points that are closer
than the given threshold
"""
result = []
if not points:
# we have no points
return result

points = array(points, dtype=float)

num_points, _ = points.shape
if num_points < 2:
return result

threshold_sq = threshold**2
points, principal_axis = _reorder_along_principal_axis(points)
for i, p in enumerate(points):
max_coord = p[principal_axis] + threshold
end = None
for j, q in enumerate(points[i + 1 :]):
if q[principal_axis] >= max_coord:
end = i + j + 1

dsq = _get_distance_sq_matrix_pairs(points[i : i + 1], points[i + 1 : end])[0]
qs = points[nonzero(dsq < threshold_sq)[0] + i + 1]

result.extend((p, q) for q in qs)

return result


def test():
points = array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(find_all_point_pairs_closer_than(points, 6))


if __name__ == "__main__":
test()
4 changes: 4 additions & 0 deletions src/modules/sbstudio/model/safety_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,16 @@ class SafetyCheckResult:
closest_pair: Optional[Tuple[Coordinate3D, Coordinate3D]] = None
min_distance: Optional[float] = None
min_altitude: Optional[float] = None
all_close_pairs: List[Tuple[Coordinate3D, Coordinate3D]] = field(
default_factory=list
)

def clear(self) -> None:
self.drones_over_max_altitude.clear()
self.drones_over_max_velocity_xy.clear()
self.drones_over_max_velocity_z.clear()
self.drones_below_min_nav_altitude.clear()
self.all_close_pairs.clear()
self.closest_pair = None
self.min_distance = None
self.min_altitude = None
4 changes: 3 additions & 1 deletion src/modules/sbstudio/plugin/materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,6 @@ def set_specular_reflection_intensity_of_material(material, intensity):
"""
material.specular_intensity = intensity
nodes = material.node_tree.nodes
nodes["Principled BSDF"].inputs["Specular"].default_value = intensity
nodes["Principled BSDF"].inputs[
"Specular IOR Level" if is_blender_4 else "Specular"
].default_value = intensity
3 changes: 2 additions & 1 deletion src/modules/sbstudio/plugin/model/formation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import bpy

from bpy.types import Collection
from functools import partial
from itertools import count
from mathutils import Vector
Expand All @@ -17,7 +18,7 @@
from sbstudio.plugin.utils.evaluator import get_position_of_object

if TYPE_CHECKING:
from bpy.types import Collection, MeshVertex, Object
from bpy.types import MeshVertex, Object

__all__ = (
"add_objects_to_formation",
Expand Down
Loading

0 comments on commit 5456750

Please sign in to comment.