Breaking Change Request: Enable isolate groups by-default - Will result in changes to Performance Characteristics

Intended change
We intend to enable isolate group sdk/issues/36097 support in the VM by-default.
This will make isolates spawned via Isolate.spawn run inside the same Isolate Group and therefore operate on the same heap, allowing sharing of various kinds of objects and allowing better communication.
Intended change in behavior:
The intention is to

make the per-isolate base memory overhead smaller (10x less RAM)
make isolates faster to spawn (10x faster spawn latency)
make isolates communicate faster (8x faster round-trip communication)
make receiver isolate of messages mostly non-blocking (removes O(n) receiver cost)
allow more rich communication between isolates (see sdk/issues/46623)
allow sharing of objects (program structure, JITed code, constants as well as any String objects - in the future possibly also user-defined data structures)
fix long-standing bugs that happen if isolates are used with the (currently non-atomic) hot-reload (e.g. flutter/issues/72195)
allow flutter to smoothly use multiple engines flutter.dev/docs/development/add-to-app/multiple-flutters

The justification/rationale for making the change
Get the improvements mentioned above to users. Enabling more data sharing of objects across isolates in the future.
The expected impact of this change
There are no functional differences. There will be changes in performance characteristics. Those changes will almost exclusively be positive.
The thread pool onto which all lightweight isolates are multiplexed onto is limited (around 10 atm), in order to ensure all threads executing on different cores have a big enough TLAB (thread local allocation buffer - a free chunk of memory from new space) to ensure fast bump allocation.
 As a consequence blocking GC operations (such as new space collections) will affect all isolates. The worst case pause time due to new space collections is unchanged, however heavily allocating isolates can impact other isolates.
In the common case where generational hypothesis holds (most objects die young) those collections continue being fast. Furthermore for Flutter specifically, any idle time on the UI thread is used to perform GCs, thereby also avoiding too long  pause due to new space GCs. (The old space is mainly collected via concurrent marking & sweeping, thereby not stopping mutators)
The only existing use case that could be negatively impacted is existing apps for which many isolates are executing in parallel on many cores (e.g. big server applications).
3 important Dart customers (including flutter) have been opt'ing into this already for a longer period of time in AOT mode. So far we have only heard positive feedback from them (especially memory footprint reductions).
We expect the only use case that might be actually affected by this change is e.g. server customers that use isolates on many threads at the same time.
Clear steps for mitigating the change
For customers that use isolates on many threads at the same time (such running on large servers), the possible workaround is to use Isolate.spawnUri()on the same application - this will cause the VM to use an independent Isolate Group which gives the old behavior. Though communication is then restricted to json-like types.
(see also go/ig-by-default)

/cc @a-siva @mraleph @aam  (VM)
/cc @Hixie @xster @gaaclarke (Flutter)
/cc @vsmenon
Feel free to CC anyone else.

To clarify, the new lightweight isolate implementation now supports both AOT and JIT right?

To clarify, the new lightweight isolate implementation now supports both AOT and JIT right?

Right.

The breaking change has been announced on here
@mit-mit Could you help get any necessary approvals (since @franklinyow is out)?

We expect the only use case that might be actually affected by this change is e.g. server customers that use isolates on many threads at the same time.

Have there been any measurements done on how much performance this might cost?
Additionally is this just a temporary pain point which will be made more performant in the future? Or is this something where the Dart team doesn't see Dart as an important use-case and thus won't optimize for?
I think espeically with the functions framework and Dart being more and more popular it might actually be become more important in the future (of course this is just my speculation).

Have there been any measurements done on how much performance this might cost?

We have done measurements on worst case scenarios. For example when 8 threads are continuously building up data structures that live for a long time (that means the generational hypothesis - which most VMs optimize for - does not hold) on 10+ GB heap can lead to a 2x slowdown.

Additionally is this just a temporary pain point which will be made more performant in the future?

Firstly, it's unclear whether any of our existing users would run into any pain points in practice (so far we are not aware of any).
We do have ideas about how this could be further optimized and might invest in that if we believe it is worthwhile.

Or is this something where the Dart team doesn't see Dart as an important use-case and thus won't optimize for?

Right now the VM team is not optimizing for large server use cases (i.e. 10-100s of cores and large amount of RAM) - because that is not how our users use Dart atm.
That being said, one can use the VM to work well in this setting - e.g. by using many isolate groups (as mentioned in the mitigation section above)

I think especially with the functions framework and Dart being more and more popular it might actually be become more
important in the future (of course this is just my speculation).

To the best of my knowledge cloud functions are often ephemerally executed, requests are independent of each other and little global state is kept. Based on that I wouldn't say this change would negatively impact such cases (it may even benefit such use cases).

Thanks for your detailed response! :)

Additionally is this just a temporary pain point which will be made more performant in the future? Or is this something where the Dart team doesn't see Dart as an important use-case and thus won't optimize for?

With spawning new isolates being at least 10x faster, potentially what we will see is that applications start start using short-lived/just-in-time-spawned isolates significantly more in addition or instead of larger long-running isolates. So in other words use of isolates could become more functions-oriented, similar to how compute in flutter is built. sendAndExit(sendPort, message) that is to be released in the future will speed up this flow even further.

Here are numbers from benchmarks we added specifically to see the impact of this change. It was measured in standalone Dart VM (JIT and AOT) on an Intel CPU:

Benchmark
JIT Before
JIT After
JIT Change
AOT Before
AOT After
AOT Change

IsolateSpawn.Dart2JSToFinishRunningRMS
3137316.00
780292.63
-75.13 %
394717.94
396074.63
0.3437 %

IsolateSpawn.Dart2JSToStartRunningRMS
89621.59
574.28
-99.36 %
17494.70
259.79
-98.52 %

IsolateSpawnMemory.Dart2JSDeltaPeakProcessRss
972947456.00
782774272.00
-19.55 %
381440000.00
258723840.00
-32.17 %

IsolateSpawnMemory.Dart2JSDeltaRssOnStart
27043156.00
3941717.00
-85.42 %
18012842.00
1769472.00
-90.18 %

IsolateSpawnMemory.Dart2JSDeltaRssOnEnd
77070336.00
551594.00
-99.28 %
108882600.00
67689128.00
-37.83 %

We measured how long it takes for a mid-to-large application (dart2js in this case) to spawn a new isolate and what the additional base memory overhead is for  such an isolate. (The helper isolate will run dart2js on a dart file)
We can see that

Spawning latency went from being O(n) in application size to being effectively a constant (JIT: 574 us, AOT: 260 us).
The spawned isolate can re-use JITed code and runs therefore much faster right from the start (it runs 4x faster).
The peak memory consumption reduces in JIT as well as AOT
The additional memory per isolate reduces by around 10x

Benchmark
JIT Before
JIT After
JIT Change
AOT Before
AOT After
AOT Change

SendPort.Receive.BinaryTree.2
5.2478
1.0162
-80.64 %
4.0722
1.2520
-69.25 %

SendPort.Receive.BinaryTree.4
12.357
1.0609
-91.41 %
6.3499
1.2568
-80.21 %

SendPort.Receive.BinaryTree.6
39.917
1.1565
-97.10 %
14.764
1.3500
-90.86 %

SendPort.Receive.BinaryTree.8
150.46
1.2812
-99.15 %
47.475
1.5075
-96.82 %

SendPort.Receive.BinaryTree.10
628.53
1.9064
-99.70 %
194.44
2.1566
-98.89 %

SendPort.Receive.BinaryTree.12
2548.28
4.2936
-99.83 %
794.96
4.3565
-99.45 %

SendPort.Receive.BinaryTree.14
10246.44
4.6576
-99.95 %
3256.48
4.6533
-99.86 %

SendPort.Receive.Json.400B
5.9036
1.1105
-81.19 %
6.3360
1.3150
-79.25 %

SendPort.Receive.Json.5KB
52.174
1.2674
-97.57 %
53.186
1.5660
-97.06 %

SendPort.Receive.Json.50KB
503.79
2.1735
-99.57 %
476.19
2.4452
-99.49 %

SendPort.Receive.Json.500KB
5194.21
5.1109
-99.90 %
4971.65
5.1561
-99.90 %

SendPort.Receive.Json.5MB
5579.90
19.9008
-99.98 %
3991.09
19.9308
-99.98 %

SendPort.Receive.Nop
0.84245
0.83353
-1.059 %
0.94660
0.95422
0.8056 %

SendPort.Send.BinaryTree.2
2.6803
0.94366
-64.79 %
2.7459
0.99268
-63.85 %

SendPort.Send.BinaryTree.4
7.5588
2.1675
-71.33 %
8.2269
2.6841
-67.37 %

SendPort.Send.BinaryTree.6
28.467
7.6131
-73.26 %
31.281
10.248
-67.24 %

SendPort.Send.BinaryTree.8
105.96
30.193
-71.51 %
117.82
30.515
-74.10 %

SendPort.Send.BinaryTree.10
419.48
110.05
-73.77 %
404.91
112.05
-72.33 %

SendPort.Send.BinaryTree.12
1738.89
544.90
-68.66 %
1739.35
523.80
-69.89 %

SendPort.Send.BinaryTree.14
7359.78
2336.84
-68.25 %
7435.21
2295.89
-69.12 %

SendPort.Send.Json.400B
5.3041
1.3875
-73.84 %
5.3811
1.2730
-76.34 %

SendPort.Send.Json.5KB
87.984
18.209
-79.30 %
83.766
18.214
-78.26 %

SendPort.Send.Json.50KB
837.65
177.17
-78.85 %
799.39
160.88
-79.88 %

SendPort.Send.Json.500KB
9134.69
2186.36
-76.07 %
8697.33
1972.85
-77.32 %

SendPort.Send.Json.5MB
113778.09
50449.93
-55.66 %
110797.18
46839.12
-57.73 %

SendPort.Send.Nop
0.30535
0.30177
-1.171 %
0.28601
0.30424
6.376 %

Here we can see that the isolate receiving messages will no longer pay a O(n) cost, it is rather constant single-digit us.
We can also see that sending json has become significantly faster, around 4x.
Together the send-and-receive is around 8x faster.

Benchmark
JIT Before
JIT After
JIT Change
AOT Before
AOT After
AOT Change

Isolate.SendReceiveBytes100KB
12903.66
25176.57
95.11 %
12683.20
25339.64
99.79 %

Isolate.SendReceiveBytes100MB
5.9831
7.3162
22.28 %
7.3251
11.073
51.17 %

Isolate.SendReceiveBytes10KB
36008.31
62362.08
73.19 %
35959.83
59863.60
66.47 %

Isolate.SendReceiveBytes10MB
59.690
55.972
-6.229 %
75.595
110.89
46.68 %

Isolate.SendReceiveBytes1KB
48756.69
80447.05
65.00 %
50621.82
78842.88
55.75 %

Isolate.SendReceiveBytes1MB
212.57
477.19
124.5 %
398.70
745.68
87.03 %

We can observe that sending bytes between isolates became between 1.5-2x faster.
(Metric is runs/second, larger numbers are therefore better)

Benchmark
JIT Before
JIT After
JIT Change
AOT Before
AOT After
AOT Change

IsolateJson.Decode100KBx1
1.7628
41.694
2265 %
19.562
38.126
94.90 %

IsolateJson.Decode100KBx4
1.2302
35.571
2791 %
11.319
34.181
202.0 %

IsolateJson.Decode1MBx1
1.0308
4.0661
294.5 %
2.3259
3.4675
49.08 %

IsolateJson.Decode1MBx4
0.67100
3.3272
395.9 %
1.3408
2.5559
90.64 %

IsolateJson.Decode250KBx1
1.4840
16.600
1019 %
8.3048
14.133
70.18 %

IsolateJson.Decode250KBx4
1.0702
11.765
999.4 %
5.1592
10.635
106.1 %

IsolateJson.Decode50KBx1
1.8633
23.011
1135 %
28.397
70.602
148.6 %

IsolateJson.Decode50KBx4
1.4497
61.380
4134 %
17.875
61.395
243.5 %

IsolateJson.SendAndExit_Decode100KBx1
1.7593
42.210
2299 %
19.747
38.317
94.04 %

IsolateJson.SendAndExit_Decode100KBx4
1.2352
36.599
2863 %
11.922
34.356
188.2 %

IsolateJson.SendAndExit_Decode1MBx1
1.0358
4.1429
300.0 %
2.3442
3.4788
48.40 %

IsolateJson.SendAndExit_Decode1MBx4
0.66169
2.3940
261.8 %
1.3342
2.4545
83.97 %

IsolateJson.SendAndExit_Decode250KBx1
1.4895
16.591
1014 %
8.2664
14.057
70.05 %

IsolateJson.SendAndExit_Decode250KBx4
1.0751
12.811
1092 %
5.2002
11.584
122.8 %

IsolateJson.SendAndExit_Decode50KBx1
1.9263
68.975
3481 %
29.038
68.695
136.6 %

IsolateJson.SendAndExit_Decode50KBx4
1.4529
61.024
4100 %
18.488
62.664
239.0 %

(Metric is runs/second, larger numbers are therefore better)
We also measure json decoding on helper isolates (in x1 or x4 isolates). The isolates are receiving bytes, perform utf-8 decoding followed by json decoding and send the result back.
We can observe

Due to re-using JITed code, the helper isolate is much faster in decoding json than before (where it had to re-JIT everything).

The faster isolate communication (which is only part of this benchmark's work) has led to a speedup of the benchmark by 1.5x-3x

Benchmark
JIT Before
JIT After
JIT Change
AOT Before
AOT After
AOT Change

EventLoopLatencyJson.Percentile95
1008.00
13815.0
1271 %
1006.00
11897.0
1083 %

EventLoopLatencyJson.Percentile99
1023.00
19878.0
1843 %
1015.00
18424.0
1715 %

EventLoopLatencyJson350KB.Percentile95
1010.00
1400.00
38.61 %
1005.00
1010.00
0.4975 %

EventLoopLatencyJson350KB.Percentile99
1018.00
2112.00
107.5 %
1012.00
1992.00
96.84 %

This shows us that if helper isolates allocate a lot of objects which die young the pause times in the main isolate are not affected much (1-2 ms). If the generational hypothesis doesn't hold (all objects survive - hypothetical worst case scenario) then the main isolate will have the same pause time as the helper isolate that triggers young collections (since young generation is collected with stop-the-world) - which is between 10-20 ms.
Though for flutter this would look different, since it will use idle time between frames to cause GCs, therefore doing more young space collections (before it's full) therefore reducing the pause times (for this hypothetical worst case scenario).

This is a very important "upgrade" to DartVM Isolate.
I want to highlight the context of changes in performance:

Isolates in the same group will collaborate with the same GC:

Since the amount of shared memory between Isolates is increased (what reduces the total number of Objects), the total CPU time of GC is reduced (if compared with multiple Isolates in separated groups).
Total JIT time is reduced (if compared with multiple Isolates in separated groups).

The current DartVM Isolate situation (Dart 2.13.4) makes impractical to spawn a high number of Isolates, due to bottlenecks (naturals to the current situation) in memory, GC and JIT.

The new approach points a theoretical decrease in performance for servers with a high number of Isolates, but this is already difficult with the current situation. The share of memory, GC and JIT can actually improve the capacity of Isolates.

Some questions?:

Will be possible to force a new spawned Isolate to be in a different group?

This can be interesting to craft a solution that separates GCs.

Will be possible to force a new spawned Isolate to be in a different group?

Isolate spawnUri (unlike Isolate spawn) spawns new isolate in its own isolate group.

It will be interesting to spawn a normal entrypoint/function (not spwanUri) in a different group, to allow specific optimizations for some solutions.

It's important to test if spawnUri, with a different projectPackageConfig still works well with all this changes.
Also, when the provided projectPackageConfig is the same of the current Isolate, this should be treated as the same "group" (if spawnUri have the ability to spawn in a current group).

Will be possible to force a new spawned Isolate to be in a different group?
This can be interesting to craft a solution that separates GCs.
This feature is important not only for spawnUri, but for any kind of entrypoint (normal Isolate.spawn).

That is indeed a very interesting question, that we also thought about.
In fact, right now we have an internal boolean flag that can be used to make Isolate.spawn(<entry>, ...) spawn <entry> in a newly created isolate group (basically the old behavior). We intentionally did not expose this in the API.
The reasons for that are multifold:

There are current limitations (which we intend to lift with this change, see sdk/issues/46623) of what isolates can send to each other. Those limitations make using isolates often hard or cumbersome (e.g. one cannot use a closure function as an <entry>). Those restrictions are currently in-place mostly because they are quite hard to implement for our current share-nothing isolates.
=> If we allowed Isolate.spawn() to spawn new isolate groups, they would be more restricted in what they can communicate. Effectively leaving the open feature requests in sdk/issues/46623 unaddressed for that use case.

Isolates created with Isolate.spawn(<entry>) are today share-nothing and run in different isolate groups. Yet we still allow them communicating user-defined objects with each other.
That poses a problem for our very popular hot-reload development feature: A hot-reload acts on one isolate group only. So there's no way to atomically perform a reload of multiple isolates (if they are of different isolate groups). Right now developer tools try to work around that by applying the same program change to all alive isolate groups (and hoping that the change gets accepted by all of them or none as well as hoping that no isolate creations are in-progress). It's a best effort that if fails can lead to crashes.
Furthermore after hot-reloads are performed and new isolates are spawned, they would need to be created by loading the initial program and applying all past reload changes. It would need to do so in a guaranteed way before that isolate interacts with others (which is hard to guarantee). It would also require the VM to keep the initial program as well as all program diffs (which can be quite big, because those program diffs are currently represented in a very course-grained way [much bigger than needed]) in-memory indefinitly, therefore effectively creating a memory leak.
=> By making Isolate.spawn() only spawn lightweight isolates within the same group, we fix all of those issues.
=> By still allowing Isolate.spawn() to spawn into new groups we leave those existing issues unfixed.

So in summary:
Isolate.spawn() is the mechanism to use to create isolates from the exact same (as well as possibly hot-reloaded) application code. We want to allow rich message exchanges between them (including user defined classes, closures, ...). It currently has a lot of issues which we are trying to solve with this work on lightweight isolates.
Isolate.spawnUri()is our mechanism to use to create isolate from possibly different application code (possibly the same app, but different hot-reloaded state). They will live in their own newly created isolate group. We intentionally restrict communication between such isolate groups to JSON-like data (no user-defined classes, closures, ...) - because there is no guarantee that the code in the spawner and spawnee isolate are compatible.
As mentioned on the mitigations, one can always use Isolate.spawnUri() on the same code as the original isolate, thereby achieving the goal of a separate isolate group, separate heap and independent GC - but one will have to accept the limited communication.
@gmpassos  It was a long explanation, but I hope it makes some sense?

So, how about 2 types of Isolates models, lightweight and fully isolated. Depending of the mode the category of shared types, between Isolates are broader or restricted. If the types sent between Isolates are controlled correctly, the issues goes away (correct me if I'm wrong).
I haven't looked at the new code, but SendPort will need to control if they are in the same group, to define the correct category of types to be shared, or issues can happen.
BTW, nice job! This is a hard and very important work.

@mkustermann Is there anywhere we can read on how isolates in an isolate group are distributed across CPU cores?

So, how about 2 types of Isolate modes, lightweight and fully isolated. Depending of the mode, the category of shared types
between Isolates are broader or restricted. If the types sent between Isolates are controlled correctly, the issues goes away
(correct me if I'm wrong).

That is precisely what happens already now:

Isolates spawned via Isolate.spawn() will run same code and allow sending rich user-defined data structures.
Isolates spawned via Isolate.spawnUri() will run (possibly different) code and only allow json-like data to be transferred.

SendPort.send() knows the destination and will apply appropriate validation on the transitive object graph (it does that already now).

BTW, nice job! This is a hard and very important work.

Glad to receive the positive feedback 👍

@mkustermann Is there anywhere we can read on how isolates in an isolate group are distributed across CPU cores?

It's not explicitly documented anywhere AFAIK.
The Dart VM is quite flexible, so the answer depends: For example in Flutter (an embedder of the Dart VM), the flutter engine will decide the specific OS thread on which the UI isolate runs and how it processes messages (helper isolates are run by the VM). When an isolate is idle and receives a message, the VM will run it's message handler on a VM-internal thread pool.
That means over the lifetime of an isolate, it may run on different OS threads. So far we have not had a need for thread-pinning support, but it may come up in the future.
The operating system is responsible for mapping OS threads (e.g. pthreads on linux) onto CPU cores. Also there a OS thread can - over it's lifetime - be running on different cores - depending on the OS scheduler. We don't do any core-pinning in the VM

@mkustermann if DartVM already have 2 modes of communication, will be good to be able to know the mode/capabilities of communication from the current Isolate.
With the correct documentation and helpers to know the current status/mode, the developer won't have surprises and will be able to craft what he needs.
I vote for:

spawnUri: Isolate in a different group (separated JIT and GC).
spawn: 2 modes

Sibling: same group (same JIT and GC) with broader types for SendPort.
Colleague: separated groups (separated JIT and GC) with a limited types for SendPort.

the mode names could be better 😎

@Hixie @vsmenon can you approve this breaking change request?

Improving performance seems great to me.

lgtm

Marking approved

Thank you all for the great discussions. The Breaking Change has been approved and we'll be performing this change sometime in the next couple of weeks (after current stable branch is cut)- allowing a long baking time on dev and beta branches.
If there's any more feature requests, performance bugs or anything else, please file a new github issue under https://github.com/dart-lang/sdk/issues/new
Last replies on this thread:

@mkustermann if DartVM already have 2 modes of communication, will be good to be able to know the mode/capabilities of
communication from the current Isolate.

With the correct documentation and helpers to know the current status/mode, the developer won't have surprises and will be
able to craft what he needs.

The documentation has recently been updated to remove some ambiguity. You can see the newest docs at SendPort.send. It lists what is always supported and what is supported if-and-only-if Isolate.spawn was used.

I vote for:

spawnUri: Isolate in a different group (separated JIT and GC).
spawn: 2 modes
Sibling: same group (same JIT and GC) with broader types for SendPort.
Colleague: separated groups (separated JIT and GC) with a limited types for SendPort.

Supporting Isolate.spawn() into new groups has its issues. As outlined above it is especially problematic with hot-reload - one could spawn before / after reload and the new isolate group would need to have before/after program state. That might lead to memory leaks of hot-reload diffs.
The complexity and issues involved in supporting this makes us believe this is not a good choice (also considering users can use Isolate.spawnUri - although a little less convenient). If there is really strong demand (with actual real world use cases where the Sibling solution is insufficient) for this, we may reconsider this.
@gmpassos If you feel strongly about it, I would encourage you to file a new github issue as a feature request, then any discussion can continue there.

About "thread-pinning":
Note that most OS and devices tries to not overheat an specific core, so it rotates the "tasks" between cores to avoid that.

What I mean by thread pinning is that a given isolate is "pinned" to a specific OS thread (e.g. pthread). There are use cases where this is needed (e.g. interacting with C code that uses thread local storage). It doesn't mean that the OS thread is pinned to a specific CPU core.

@mkustermann thanks for the response.
About the "spawn in a separated group":
Now I understand better the complexity to implement it. I think that "spawnUri" and "Platform.script"
(https://api.dartlang.org/stable/dart-io/Platform/script.html) can resolve most use cases when lightweight Isolates goes to production.
About OS Thread pinning, this can be very useful to avoid issues with "dart:ffi". Also will help integrations with C/C++ or existing compiled libraries that need that.
Look the issues that Python has and the use of GIL (Global Interpreter Lock), that is mandatory, an approach that is totally wrong for me.
Regards.

Can we create/post some sample code for this? Also cc @RedBrogdon for devrel.

Can we create/post some sample code for this?

That'd be nice! But please note that this won't be in stable until 2.15.

The flag is now on by-default in all modes. Closing this issue.

Can we create/post some sample code for this? Also cc @RedBrogdon for devrel.

We'll ensure there's good documentation by the time the stable is released.

Any chance there's any detailed doc on migrating to Isolate.spawnUir() to preserve legacy behaviour of isolates? While refactoring my code I've managed to launch isolates via this method yet there's native crash, most likely on the main isolate side when receiving messages from spawned isolates via SendPort/ReceivePort it there's little I was able to fin on the internet that might help with troubleshooting:
../../runtime/vm/message_snapshot.cc: 557: error: expected: !cls.IsNull()
version=2.14.4 (stable) (Wed Oct 13 11:11:32 2021 +0200) on "macos_x64"
pid=80103, thread=13323, isolate_group=main(0x7f9a58926000), isolate=main(0x7f9a5892b000)
isolate_instructions=10bdf30a0, vm_instructions=10bdf30a0
  pc 0x000000010c05b154 fp 0x000070000a3f3b00 dart::Profiler::DumpStackTrace(void*)+0x64
  pc 0x000000010bdf3274 fp 0x000070000a3f3be0 dart::Assert::Fail(char const*, ...)+0x84
  pc 0x000000010bfbf71a fp 0x000070000a3f3c40 dart::ReadApiMessage(dart::Zone*, dart::Message*)+0x896a
  pc 0x000000010bfb6334 fp 0x000070000a3f3cb0 dart::MessageDeserializer::Deserialize()+0x274
  pc 0x000000010bfb6d6f fp 0x000070000a3f3d00 dart::ReadMessage(dart::Thread*, dart::Message*)+0x5f

  pc 0x000000010bf849c9 fp 0x000070000a3f3de0 dart::IsolateMessageHandler::HandleMessage(std::__2::unique_ptr<dart::Message, std::__2::default_delete<dart::Message> >)+0x1a9
  pc 0x000000010bfb1d4c fp 0x000070000a3f3e50 dart::MessageHandler::HandleMessages(dart::MonitorLocker*, bool, bool)+0x12c
  pc 0x000000010bfb247f fp 0x000070000a3f3eb0 dart::MessageHandler::TaskCallback()+0x1df
  pc 0x000000010c0e5bd8 fp 0x000070000a3f3f30 dart::ThreadPool::WorkerLoop(dart::ThreadPool::Worker*)+0x148
  pc 0x000000010c0e603d fp 0x000070000a3f3f60 dart::ThreadPool::Worker::Main(unsigned long)+0x5d
  pc 0x000000010c055b1f fp 0x000070000a3f3fb0 dart::OSThread::GetMaxStackSize()+0xaf
  pc 0x00007ff818400514 fp 0x000070000a3f3fd0 _pthread_start+0x7d
  pc 0x00007ff8183fc02f fp 0x000070000a3f3ff0 thread_start+0xf
-- End of DumpStackTrace

Any chance there's a detailed doc on migration to Isolate.spawnUir() to preserve legacy behaviour of isolates?

Generally speaking spawnUri'ed isolates have limitations regarding what can be sent to them that have to be worked around(https://api.dart.dev/dev/2.16.0-0.0.dev/dart-isolate/SendPort/send.html), they can not be used as a direct replacement of spawn'ed isolates(lightweight or legacy heavyweight). Also note that spawnUri is not supported in AOT configuration

While refactoring my code I've managed to launch isolates via this method yet there's native crash, most likely on the main isolate side when receiving messages from spawned isolates via SendPort/ReceivePort it there's little I was able to fin on the internet that might help with troubleshooting:

Sorry about the crash. Would you mind opening up a new issue with hopefully some instructions on how to reproduce it?

../../runtime/vm/message_snapshot.cc: 557: error: expected: !cls.IsNull()
version=2.14.4 (stable) (Wed Oct 13 11:11:32 2021 +0200) on "macos_x64"
pid=80103, thread=13323, isolate_group=main(0x7f9a58926000), isolate=main(0x7f9a5892b000)
isolate_instructions=10bdf30a0, vm_instructions=10bdf30a0
  pc 0x000000010c05b154 fp 0x000070000a3f3b00 dart::Profiler::DumpStackTrace(void*)+0x64
  pc 0x000000010bdf3274 fp 0x000070000a3f3be0 dart::Assert::Fail(char const*, ...)+0x84
  pc 0x000000010bfbf71a fp 0x000070000a3f3c40 dart::ReadApiMessage(dart::Zone*, dart::Message*)+0x896a
  pc 0x000000010bfb6334 fp 0x000070000a3f3cb0 dart::MessageDeserializer::Deserialize()+0x274
  pc 0x000000010bfb6d6f fp 0x000070000a3f3d00 dart::ReadMessage(dart::Thread*, dart::Message*)+0x5f

  pc 0x000000010bf849c9 fp 0x000070000a3f3de0 dart::IsolateMessageHandler::HandleMessage(std::__2::unique_ptr<dart::Message, std::__2::default_delete<dart::Message> >)+0x1a9
  pc 0x000000010bfb1d4c fp 0x000070000a3f3e50 dart::MessageHandler::HandleMessages(dart::MonitorLocker*, bool, bool)+0x12c
  pc 0x000000010bfb247f fp 0x000070000a3f3eb0 dart::MessageHandler::TaskCallback()+0x1df
  pc 0x000000010c0e5bd8 fp 0x000070000a3f3f30 dart::ThreadPool::WorkerLoop(dart::ThreadPool::Worker*)+0x148
  pc 0x000000010c0e603d fp 0x000070000a3f3f60 dart::ThreadPool::Worker::Main(unsigned long)+0x5d
  pc 0x000000010c055b1f fp 0x000070000a3f3fb0 dart::OSThread::GetMaxStackSize()+0xaf
  pc 0x00007ff818400514 fp 0x000070000a3f3fd0 _pthread_start+0x7d
  pc 0x00007ff8183fc02f fp 0x000070000a3f3ff0 thread_start+0xf
-- End of DumpStackTrace

@aam thanks for the clarifications! Incompatibility of spawnUri() with AOT effectively means you can't use it with Flutter...
The above logs come from DartVM running unit tests and most probable cause is the kind of payload that was OK with legacy spawn() is now not supported in spawnUri() - don't think it is worth a separate Issue.
P.S.: I'm opening a separate issues regarding performance troubles with this feature shortly.
P.P.S: Having some toggle for old heavyweight isolates would be a remedy for my app.

@aam thanks for the clarifications! Incompatibility of spawnUri() with AOT effectively means you can't use it with Flutter...

To provide further clarification - conceptually when using spawnUri in AOT you would have to point at dart vm snapshot, rather than .dart-source code. If you do that, dart vm should be able to spawn new isolate group from the snapshot you provided. This has not been well documented or provisioned in [flutter, for example] AOT build flow. Basically those aot vm snapshots have to be built/prepared ahead of time, build/distribution setup has to ensure that children snapshots are compatible with parent snapshots.
Before diving deeper into this it would be helpful to understand the use case that requires spawnUri(in flutter or anywhere else), rather than spawn.

The above logs come from DartVM running unit tests and most probable cause is the kind of payload that was OK with legacy spawn() is now not supported in spawnUri() - don't think it is worth a separate Issue.

It would help if you could share command line of how the unit tests were launched and revision of dart sdk where you see this happening. It should not be happening. :-)

P.S.: I'm opening a separate issues regarding performance troubles with this breaking change shortly. P.P.S: Having some toggle for old heavyweight isolates would be a remedy for my app.

Okay, please cc me and @mkustermann on those.

@mkustermann, you mention sharing String objects between Isolates of a same group ("allow sharing of objects (program structure, JITed code, constants as well as any String objects - in the future possibly also user-defined data structures)").
How is this done ? Is this only internal to the engine ?

... you mention sharing String objects between Isolates of a same group. ... How is this done ? Is this only internal to the engine ?

When sending messages (e.g. via SendPort.send(<message>)) to other isolates that were spawned using Isolate.spawn() (or higher-level wrappers, e.g. flutter's compute() function) the <message> graph is transitively copied, but certain objects in there are not copied but shared, that includes String objects.
That means if you e.g. spawn an isolate, which loads data from the internet and decodes the bytes to a string, you can send that string to the UI isolate in O(1) time and it will be sent by-pointer.
We can do that because String objects (as some other objects) are transitively immutable.

Ah ok, here I thought there was a way to access shared memory freely, I misunderstood.
Is there any plans of adding a way for pointers to any object to be transmissible ? This would be highly useful when downloading big json payloads (thousands of objects).

Is there any plans of adding a way for pointers to any object to be transmissible ? This would be highly useful when downloading big json payloads (thousands of objects).

We do have some limited support using Isolate.exit() it avoids a transitive copy by exiting the current isolate and giving the message to the receiver isolate by-pointer. Though it still performs a possibly O(n) verification pass on the sender side.
There have been some talks about allowing general shared (mutable) memory (as e.g. Java) - though we have no concrete plans atm to introduce that.

@mtc-jed I'd love if you could try the Isolate.exit() approach Martin mentions, and then give us your feedback on whether that worked or not. As Martin details, the verification pass is on the sender side, so that should not cause any slowdown of your UI on the main isolate.

Not an Isolate solution, but still a shared pointer solution for the Dart VM:
I needed to implement something similar and one way was through dart:ffi.
Take a look at:
https://github.com/eneural-net/async_task/blob/master/lib/src/async_task_shared_pointer.dart#L266
Note that the shared pointer (and related memory segment) won't have any concurrency control (no MUTEX). So it only works for some scenarios, where one side only writes and the other side reads and is capable to know if the read operation was successful.
If dart:ffi had some MUTEX control to access a pointer's bytes it will be possible to do a lot of interesting things.
Another important thing about Isolate communication:

I didn't known that String (an immutable object) won't be copied between Isolates. Maybe this subject requires some documentation.
Are const instances copied between Isolates? How this is actually allocated in the VM between Isolates?
Immutable Lists, Sets and Maps could have some way to create them as immutable and shared/"uncopied" between Isolates. For now we only have immutable views of this collections, not an actual immutable object like String.

Note that in some applications where we use Isolates to use all the cores of the computer the time that it takes to return the data is significant, but we are not using the Isolate.exit approach since we need to keep the Isolate running, since won't be efficient to recreate it and send all the initial data to be processed. Isolate.exit is a nice strategy but it's an antagonist of the bootstrap of a task in a new Isolate.

@gmpassos Very cool, however this only works with a list of bytes. I am not aware of any way in Dart of casting any random user-defined object to its bytes.

@mit-mit Running tests in 2.16.1, I get a linearly growning delay between the call to Isolate.exit() and the running of a print() in the calling Isolate. This seems in line with the behaviour described by @mkustermann.
I will probably use the Isolate.exit() method for my particular use case (one-time download of a bunch of data, in order for the app to be able function without an internet connection), since it is clearly adapted.
That being said, a pass by pointer would very much be appreciated, not only by myself but also by a lot of other people (the benefits of this for a local database could be tremendous, I believe).
The question that's bugging me is : What is gained by preventing developpers frop passing pointers to other Isolates ?
Here's how a data downloading would be with pointer passing :
I start my Flutter app. An Isolate is spawned to handle data downloading, and deserialization to a user-defined object.
I order my Isolate to download data, and the Isolate responds after a time with a pointer to the object.
Repeat however many times you want.
Cost to the main Isolate : 1 Isolate.spawn() at app startup.
Without pointer passing, we can only :

Pass by value. The main Isolate incurres the cost of deserialization.
Use Isolate.exit(). The main Isolate incurres the cost of spawning a new Isolate for every download.

I do not see, AFAIK, a reason to prevent the developers from implementing this use case. I of course have only barebones knownledge of the Dart VM and of the general philosophy applied when developping the language ; feel free to enlighten me.
I am of the opinion that developers should be given as much freedom as possible, provided the right tools to manage that freedom are available. In addition to this, implementation of such a solution seems trivial given the work already done for Isolate.exit() is closely related (I could be 100% wrong on this).
To note : Isolate spawning is apparently way less costly with 2.15's Isolate groups. So Isolate.exit() seems like a sustainable solution, but there's no denying it could be much better with pointer passing.

You can use:
https://pub.dev/packages/data_serializer
And make your object implement:
https://pub.dev/documentation/data_serializer/latest/data_serializer/Writable-class.html

@gmpassos This would mean I still have to deserialize my data in the main Isolate, which is exactly the cost I'm trying to avoid.

Yes I agree. To have the original allocated memory delegated from one Isolate to another the only way now is with 'Isolate.exit'

The question that's bugging me is : What is gained by preventing developpers frop passing pointers to other Isolates ?

It's a language level design decision - allowing to pass arbitrary objects around creates shared memory with all associated issues and pitfalls. So a simpler programming model is gained by outlawing shared memory.
That being said I suggest to move discussions about shared memory into other channels - it is offtopic here.
If you want to outline specific issues you are facing, there is https://github.com/dart-lang/language/issues/333

Maybe this issue isn't the right place for this discussion. Could I ask you to open new issues for feature requests / bug reports?
Regarding dart:ffi
Yes it's the escape from the sound and safe world. It allows unsafe access to shared writable C memory from multiple isolates.
Using dart:ffi it is also possible to call into C for auxiliary things (e.g. acquire/release locks, release/acquire memory order, fences, atomics, etc.) Maybe we will eventually provide some of those primitives in dart:ffi itself instead of needing to call out to C code.
Especially regarding blocking synchronization mechanisms like locks, I'd like to mention that use of such must be done with care: Dart's eventloop based programming model is based on the fact that Dart code doesn't synchronously block for longer periods of time. This is especially important for Flutter apps where the UI isolate needs to be able to render animations with 60+fps.

That being said I suggest to move discussions about shared memory into other channels - it is offtopic here.

Can be a little bit out of topic. Bu actually we are talking about shared memory as an alternative of the issues of how to send large amount of data or complex objects between Isolates. Actually we don't want to use shared memory, we prefer an elegant and native approach. The idea here is just to show how we are bypassing the performance issue, so the awesome job done with Isolate groups achieve its full potential.
Best regards.


[icu] Build error

Host Environment

OS: Windows 11 -  WSL2 - Linux Pango <IP_ADDRESS>-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Compiler: g++ 10.3.0

To Reproduce
Steps to reproduce the behavior:
./vcpkg install icu
Failure logs
Console:
The following packages will be built and installed:
    icu[core]:x64-linux -> 70.1
Detecting compiler hash for triplet x64-linux...
Restored 0 packages from /home/joel/.cache/vcpkg/archives in 10.05 us. Use --debug to see more details.
Starting package 1/1: icu:x64-linux
Building package icu[core]:x64-linux...
-- Using cached icu4c-70_1-src.tgz.
-- Cleaning sources at /home/joel/vcpkg/buildtrees/icu/src/c-70_1-src-a6ee276eef.clean. Use --editable to skip cleaning for the packages you specify.
-- Extracting source /home/joel/vcpkg/downloads/icu4c-70_1-src.tgz
-- Applying patch disable-escapestr-tool.patch
-- Applying patch remove-MD-from-configure.patch
-- Applying patch fix_parallel_build_on_windows.patch
-- Applying patch fix-extra.patch
-- Applying patch mingw-dll-install.patch
-- Applying patch disable-static-prefix.patch
-- Applying patch fix-win-build.patch
-- Using source at /home/joel/vcpkg/buildtrees/icu/src/c-70_1-src-a6ee276eef.clean
-- Getting CMake variables for x64-linux-dbg
-- Getting CMake variables for x64-linux-rel
-- Generating configure for x64-linux
-- Finished generating configure for x64-linux
-- Configuring x64-linux-dbg
CMake Error at scripts/cmake/vcpkg_execute_required_process.cmake:128 (message):
    Command failed: /usr/bin/bash -c "V=1 ./../src/c-70_1-src-a6ee276eef.clean/source/configure  \"--disable-samples\" \"--disable-tests\" \"--disable-layoutex\" \"--disable-silent-rules\" \"--verbose\" \"--disable-shared\" \"--enable-static\" \"--enable-debug\" \"--disable-release\" \"--prefix=/home/joel/vcpkg/installed/x64-linux/debug\" \"--bindir=\\${prefix}/../tools/icu/debug/bin\" \"--sbindir=\\${prefix}/../tools/icu/debug/sbin\" \"--libdir=\\${prefix}/lib\" \"--includedir=\\${prefix}/../include\" \"--datarootdir=\\${prefix}/share/icu\""
    Working Directory: /home/joel/vcpkg/buildtrees/icu/x64-linux-dbg
    Error code: 2
    See logs for more information:
      /home/joel/vcpkg/buildtrees/icu/config-x64-linux-dbg-out.log
      /home/joel/vcpkg/buildtrees/icu/config-x64-linux-dbg-err.log

Call Stack (most recent call first):
  scripts/cmake/vcpkg_configure_make.cmake:815 (vcpkg_execute_required_process)
  ports/icu/portfile.cmake:52 (vcpkg_configure_make)
  scripts/ports.cmake:145 (include)

error: building icu:x64-linux failed with: BUILD_FAILED

> cat /home/joel/vcpkg/buildtrees/icu/config-x64-linux-dbg-err.log
configure: WARNING: unrecognized options: --disable-silent-rules
./../src/c-70_1-src-a6ee276eef.clean/source/configure: line 7981: syntax error near unexpected token `newline'
./../src/c-70_1-src-a6ee276eef.clean/source/configure: line 7981: `AX_CHECK_COMPILE_FLAG('

@jwpleow Thanks for posting this issue, could you please run command sudo apt -y install autoconf-archive and try again.

thanks .谢谢你的解决方法
@FrankXie05

@jwpleow does the issue still occur?

@jwpleow Thanks for posting this issue, could you please run command sudo apt -y install autoconf-archive and try again?

This works. Thank you!


Critical CSS critters package causing linting errors

Hello,
I just added ViteSSG to an existing Vite + Vue 3 + TypeScript app, but unfortunately when linting the app with vue-tsc --noEmit I get this output:
$ vue-tsc --noEmit
node_modules/vite-ssg/dist/types-5566f955.d.ts:4:25 - error TS2307:
Cannot find module 'critters' or its corresponding type declarations.

4 import { Options } from 'critters';
                          ~~~~~~~~~~

Found 1 error.

It this something that needs fixing on ViteSSG's side?
Note: If I skip the linting step and build directly with vite-ssg build it builds just fine.

I would suggest adding "skipLibCheck": true to your tsconfig.json

Thanks, that worked and also sped up the linting process by a lot. :tada:


support PID attached

I hope，  this agent can support PID attached。Thanks~

The code implementation can be referred to arex-attacher
I will close this issue. If you have any questions, please reopen it.


Generate bytes entry for table properties

Desired Behaviour
Automatically set the value of the bytes property to the number of bytes used when the data package is exported.
This property should be set for each table in the data package.
This will help when uploading the data package to CKAN.

/remind me to update the acceptance test on Jun 1

I've added this to the set table properties acceptance test. It maybe better place in the Save file features. Feedback welcome.


MINOR: Execute action queue after callback request

KIP-890 part 1 introduced the callback request type. It is used to execute a callback after KafkaApis.handle has returned. We did not account for tryCompleteActions at the end of handle when making this change.
In tests, we saw produce p99 increase dramatically (likely because we have to wait for another request before we can complete DelayedProduce). As a result, we should add the tryCompleteActions after the callback as well. In testing, this improved the produce performance.
Committer Checklist (excluded from commit message)

[ ] Verify design and implementation
[ ] Verify test coverage and CI build status
[ ] Verify documentation (including upgrade notes)

I recommend turning off whitespace changes so that the diff renders correctly.


feat: optional wake lock

resolve #1552.

Awesome idea!

I think we could have it enabled by default (when the app is on the front). With a client button and context menu to toggle it. And the frontmatter option can disable this feature completely

I think we could have it enabled by default (when the app is on the front). With a client button and context menu to toggle it. And the frontmatter option can disable this feature completely.
In client, the state can be Keep awake when slides in front Always keep awake Do not keep awake

Added this option to the settings popover:

If the tab is not on the front, the wake lock will become effectless automatically by the browser.


iOS: Missing UI on QR code scan screen

Some of the UI elements are missing on iOS on the QR code screen. As you can see in the screenshot, the tiny QR code icon, a bit of text, as well the alignment square on top of the camera feed is missing. This is on an iPhone SE 2020.

Here is what the same screen looks like on Android:

Hello, sorry for the late response, it's been busy so I'm not able to respond to the tickets quickly.
Does this affect the camera functionality? The android and iOS ui are implemented differently and they're a part of base cardboard sdk from official repository.
Unless there is a bug, I won't fix it.
If it really affects your project:
https://github.com/mobfishgmbh/cardboard
This is the base sdk repository, forked directly from official repository. You can change the UIs there.
Detail on how to build it for Unity can be found here:
https://github.com/mobfishgmbh/Cardboard-VR-Unity-SDK/wiki/Build-Cardboard-iOS-SDK-for-Unity

I have just got the same issue - it is kind of breaking for iOS as the screen does not make much sense
(not that it is particularly well explained what you are doing when it works!! - thanks google)


LUN-329: Show correct header for scope selection

This pull request belongs to an issue on our bugtracker.
You can find it there by looking for an issue with the key which is mentioned in the title of this pull request.
It starts with the keyword LUN.
Needed to change from navigate to push for ScopeSelectionScreen and ProfessionSelectionScreen, as navigate would use the first and second screen in the stack form initial view, which will break our stack-logic. Other solution would be to clear the stack when navigation to the HomeScreen after initial selection, but as it works fine to navigate to the home screen and navigate back to initial selection (with hardware buttons), i think this way it is the better option.

@klinzo Do you prefer reseting the history or using push?

@klinzo Do you prefer reseting the history or using push?

I definitely prefer using push over resetting the history, nothing wrong with push, it's a public api of react-navigation (at least as long as there is a reason to use it over navigate). Still not sure I really understood why we need it though.

@klinzo Do you prefer reseting the history or using push?

I definitely prefer using push over resetting the history, nothing wrong with push, it's a public api of react-navigation (at least as long as there is a reason to use it over navigate). Still not sure I really understood why we need it though.

When starting the app for the first time select a discipline, confirm and then got to "settings" and want to add a new discipline

ScopeSelection
DisciplineSelection
Home
ManageDisciplines

so now with "add new discipline", we trigger the navigation to ScopeSelection, when using navigation.navigate('ScopeSelection') we would jump to 1) and our history will have only one entry:

ScopeSelection

when using navigation.push('ScopeSelection) our history will look like this:

ScopeSelection
DisciplineSelection
Home
ManageDisciplines
ScopeSelection

And therefore back navigation works.

@klinzo Do you prefer reseting the history or using push?

I definitely prefer using push over resetting the history, nothing wrong with push, it's a public api of react-navigation (at least as long as there is a reason to use it over navigate). Still not sure I really understood why we need it though.

When starting the app for the first time select a discipline, confirm and then got to "settings" and want to add a new discipline our history looks like this:
1. ScopeSelection

2. DisciplineSelection

3. Home

4. ManageDisciplines

so now with "add new discipline", we trigger the navigation to ScopeSelection, when using navigation.navigate('ScopeSelection') we would jump to 1) and our history will have only one entry (back navigation will fail as we are on the first entry of the history):
1. ScopeSelection

when using navigation.push('ScopeSelection) our history will look like this:
1. ScopeSelection

2. DisciplineSelection

3. Home

4. ManageDisciplines

5. ScopeSelection

And therefore back navigation works.

Thanks for explaining, now I understand. Perhaps reset is then the better solution since we never want to go back to the first two screens :see_no_evil: This is more like an intro screen then and should be replaced completely. Keeping the routes may lead to issues later on (like displaying a back button or going back if the hardware back button even though it is unwanted). Sorry for changing my mind here.

@SteffiStuffel it is even the case that it is possible to go back from the home screen to the initial selection. I don't think that should be possible right? So we should use reset here.

@SteffiStuffel it is even the case that it is possible to go back from the home screen to the initial selection. I don't think that should be possible right? So we should use reset here.

Yes it is possible and also works, but not really the user flow we want to encourage. I'm fine with resetting


Rancher 2.2 Alpha 6 - meaningful cluster name

What kind of request is this (question/bug/enhancement/feature request):
enhancement
Steps to reproduce (least amount of steps as possible):
Generate alert
Result:
Alert Name: Etcd member has no leader
Severity: critical
Cluster Name: c-l7zln
Namespace: cattle-prometheus
Expression: etcd_server_has_leader{job="exporter-kube-etcd-cluster-monitoring"}==1
Description: Threshold Crossed: datapoint value 1 was equal to the threshold (1) for (30s)
Expected Result
A meaningful  cluster name but not 'Cluster Name: c-l7zln'  if Rancher going to manage a lot of environments.

the clusterName is updated in master now, will release soon, will look like Cluster Name: mycluster(ID: c-l7zln)

Version: master 2.2 (2/27/19) Image ID: bf5e00877a76
Confirmed fixed.


BBC unit tests

Add unit tests for bbc and smileys. Also mail mimespecialchars(), search prepareSearchContext(), xmlArray _from_cdata().
For #762.

BBC are now tested.
Smiley no.
_from_cdata neither.
prepareSearchContext is probably prepareSearchContext_callback and needs tests for the entity_fix__callback preg_replace.
But considering so many tests are missing, I don't see the point in having this issue.


How to make ionic 1 iOS app go transparent?

I'm currently using the plugin and the functions works, but my problem is there's no camera preview on it. Please help me.

you have to maje your html{ opacity : 0 }

@xcarlo31 there are a few other elements that need to be transparent. This works with Ionic 3: https://github.com/bambuser/bambuser-examplebroadcaster-ionic/blob/master/src/pages/broadcaster/broadcaster.scss#L6-L11
https://github.com/bambuser/bambuser-examplebroadcaster-ionic/blob/master/src/pages/broadcaster/broadcaster.ts#L39
Something similar (but not identical) for Ionic 1 probably. Use ionic serve + the DOM inspector to figure it out.


Using vins on OAK-D-PRO

Hi, I am a beginner at VINS. We are currently trying to implement vins using Oak-d-pro. The environment I am using is Ubuntu 20.04, ROS 1 nonetic, and opencv 4. I feel quite confused after following the code configuration above. I am not sure how to establish a connection with the oak-ros simple mentioned under the oak-d branch, and how to run the currently configured vins code to achieve the effect you demonstrated. If it won't take up too much of your time, could you please guide me on what I should do to run it after configuring the config.yaml and Calibration data under the branch.Thanks a lot!

Should oakd ros simple be installed in the same src folder as this Vins?

@ahjcahkl

Install VIO algorithm you want, set the config files properly - it usually contains the topic names of images and IMU. So type the output from oakd ROS node there.
Then run the oakd ROS node and VIO algorithm node. They do not have to be in the same folder but just built properly so that they can be run as executable nodes.
vins_estimator/launch/vins_rviz.launch is for the VINS-Fusion algorithm and only for running the Rviz node. So you can just ignore this.
I linked original repositories here - https://github.com/engcang/vins-application/?tab=readme-ov-file#0-algorithms and check out how to run the each algorithm from the official repositories, please.
This repository mainly focuses on build process and trouble shooting plus applications of many VIO algorithms as written here -https://github.com/engcang/vins-application?tab=readme-ov-file#mainly-focused-on-build-process-and-explanation but not any official repositories of VIO algorithms listed. So you should check official repository together.
Please note again, this repository mainly focuses on build process and trouble shooting and comparisons or applications of VIOs.


Add getting started tutorial and tutorial section

Ready for next review round. I'll update the RELEASE_NOTES once @llucax is happy.

It's not merging because it seems some commits are not signed.

It's not merging because it seems some commits are not signed.

weird. No they are!


As a user, I'd love to know how to connect with the services I start, so I can take more advantage of what Grid has to offer.

what does this mean/look like @evertonfraga?

this user story got more complex with the dynamic plugin architecture. the
initial idea was to display a pane after node has started instructing the
user. example:
“You have started Geth.
Here are some ways to use it:

You can connect with MetaMask using https://localhost:8545
Use console with command `geth —datadir ~/privatenet console”

i’d argue this can be done when we make an “UI audit”, because there are
lots of ways to aid the user.
On Mon, Jul 1, 2019 at 8:30 PM Marc Garreau<EMAIL_ADDRESS>wrote:

what does this mean/look like @evertonfraga
https://github.com/evertonfraga?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ethereum/grid/issues/253?email_source=notifications&email_token=AAALQBALLINM4NJJBQ66G5TP5KOT7A5CNFSM4HXJ75VKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY7WWFA#issuecomment-507472660,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAALQBAGGGEYQC6IP6YPQ2LP5KOT7ANCNFSM4HXJ75VA
.


Wizard: Get distribution repositories from an api endpoint

Previously the base repository links for each distribution were read from repos.js file. This gets the needed information from a call to api endpoint architectures/{distribution}. The data is fetched via RTK Query and is then filtered by an architecture. For now the x86_64 architecture is hardcoded, this will change when multiple architectures get available.

Alright, this one is finally ready for review!
Note about tests:
To mock the api response the tests are now using msw instead of previously used jest mockImplementation. That means that at the same time, the new way of api mocking and the old way are now coexisting within the test files.
This was causing problems in tests:

Step Packages -> chosen packages can be reset after filtering
Click through all steps -> with valid values

both in beta and non-beta tests as the mockImplementation was overriding the results of msw. For this reason I've updated values the tests are looking for in these cases to fit the mocked results of
const getPackages = jest

.spyOn(api, 'getPackagesContentSources')

.mockImplementation(() =>

Promise.resolve(mockPkgResultAlphaContentSources)

);

As the tests are checking for the presence of a package and are not working with it further this shouldn't have any effect on their reliability.
Unification of the mocks might be an issue on its own, what do you think?

/retest


update Gripp3r README

Dear @laurensvalk, @dlech
Here are my changes for Gripp3r.
Thank you very much!
Antoni

Dear @dlech and @laurensvalk,
Gripp3r is ready for your review.
Thank you very much!
Antoni


fix: question difficulty

Summary by Sourcery
Fix the difficulty level of a question in the pointgroups_2.json file by changing it from 'advanced' to 'basic'.
Bug Fixes:

Correct the difficulty level of a question from 'advanced' to 'basic' in the pointgroups_2.json file.

strange that the action fails

Thanks for the fix!


Issue calculating a school

Oi mate,
tried to calculate my school. I dont know why but it doesnt seem to work. Not even calculating the needs for audio works correctly.  The problem is that the "author" isnt using a main method but rather onEnable(). When I ran the code through a plagiarism tool it showed me its 90% ChatGPT. I will open a new repository with the fixed code.

bet


Can`t use this with Composer 2.0.x

Now Composer 2 version is stable, so when I do
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php composer.phar --version
In a project that uses Carbon (I`m working on a laravel/lumen 5.7 project that uses Carbon 1), I receive

PHP Fatal error:  Class UpdateHelper\ComposerPlugin contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Composer\Plugin\PluginInterface::deactivate, Composer\Plugin\PluginInterface::uninstall) in /path/to/my/project/vendor/kylekatarnls/update-helper/src/UpdateHelper/ComposerPlugin.php on line 11
Fatal error: Class UpdateHelper\ComposerPlugin contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Composer\Plugin\PluginInterface::deactivate, Composer\Plugin\PluginInterface::uninstall) in /path/to/my/project/vendor/kylekatarnls/update-helper/src/UpdateHelper/ComposerPlugin.php on line 11

For me, a workaround is install the latest 1 version of composer
php composer-setup.php --version=1.10.16
Any chance to solve this?

Support of Composer 2 is in progress. Note that you get update-helper installed because you have a deprecated package in your stack (Lumen 5.7 is now very old). As you seem to appreciate being up to date with Composer, please consider being so with Lumen.

Hello, I just checked with a fresh install of Composer 2.0.3 and ran ./composer.phar require nesbot/carbon:^1, this installed it smoothly. So my guess is that you have an old version of update-helper (< 1.2.1), so you should first updatre (with --no-scripts flag), then running other install/update after that should work normally.
We can't provide any fix for that as obviously we can't change the code of a version already released and installed on your machine.
Mostly the root cause is it has been previously installed with Composer 1 (or composer.lock was generated with Composer 1) and you upgrade to Composer 2 before updating the project dependencies/composer.lock.
If you think it's a different problem, please provide a complete list of commands I can execute to reproduce the bug and I'll re-open.
Thanks.

--no-scripts didn't work for me, I had to use --no-plugins


Fix Phantom JS failures

The master build is failing in Concourse because spec:javascript was added to the default rake task but PhantomJS isn't installed in the container (but is available as a gem) so the tests are failing with "sh: 1: phantomjs: not found".
https://cd.gds-reliability.engineering/teams/govuk-tools/pipelines/govuk-corona-find-support-form/jobs/run-quality-checks/builds/172
This will (hopefully) fixes the issue by using the gem for PhantomJS commands.
Paired with @leenagupte on this.

PhantomJS is very deprecated. Could we explore some alternatives? 🤔

@issyl0 yes we could! Lets get this merged in first, so we can deploy, then look at alternatives :)


Theme

General refactoring of some theme related functions. Removed some stuff. Added a Templates class.

Broken merge, you probably started from an outdated development branch, you should rebase...
Also for consistency, can it be named Templates.class.php? :angel:

The travis-ci tests are broken for the BBC parser. They don't run loadTheme(). I will attempt to get tests working locally tomorrow but everything else seems to be right.

lol at the last commit message! :p


The time stamp is not correct for some midi file

For example, I convert my midi  in https://tonejs.github.io/Midi/ to this:
{
  "header": {
    "keySignatures": [],
    "meta": [
      {
        "ticks": 0,
        "type": "sequencerSpecific"
      },
      {
        "ticks": 0,
        "type": "sequencerSpecific"
      },
      {
        "ticks": 0,
        "type": "sequencerSpecific"
      }
    ],
    "name": "",
    "ppq": 960,
    "tempos": [
      {
        "bpm":<PHONE_NUMBER>3340972,
        "ticks": 0
      }
    ],
    "timeSignatures": [
      {
        "ticks": 0,
        "timeSignature": [
          4,
          4
        ],
        "measures": 0
      }
    ]
  },
  "tracks": [
    {
      "channel": 0,
      "controlChanges": {},
      "pitchBends": [],
      "instrument": {
        "family": "piano",
        "name": "acoustic grand piano",
        "number": 0
      },
      "name": "Track 1",
      "notes": [
        {
          "duration": 0.27272750000000023,
          "durationTicks": 480,
          "midi": 74,
          "name": "D5",
          "ticks": 2640,
          "time": 1.50000125,
          "velocity": 0.5039370078740157
        },
        {
          "duration": 0.2727274999999998,
          "durationTicks": 480,
          "midi": 70,
          "name": "A#4",
          "ticks": 4080,
          "time": 2.31818375,
          "velocity": 0.5039370078740157
        },
        {
          "duration": 0.27272750000000023,
          "durationTicks": 480,
          "midi": 77,
          "name": "F5",
          "ticks": 5280,
          "time": 3.0000025,
          "velocity": 0.5039370078740157
        },
        {
          "duration": 0.2727274999999998,
          "durationTicks": 480,
          "midi": 67,
          "name": "G4",
          "ticks": 6960,
          "time": 3.9545487500000003,
          "velocity": 0.5039370078740157
        },
        {
          "duration": 0.545455,
          "durationTicks": 960,
          "midi": 71,
          "name": "B4",
          "ticks": 6960,
          "time": 3.9545487500000003,
          "velocity": 0.5039370078740157
        },
        {
          "duration": 0.27272750000000023,
          "durationTicks": 480,
          "midi": 75,
          "name": "D#5",
          "ticks": 8160,
          "time": 4.6363675,
          "velocity": 0.5039370078740157
        }
      ]
    }
  ]
}

But  the time is not correct  after parsing with MidiParser. Here is the result:
Name time duration
--------------------
D6      2.75     0.5
A#5   4.25      0.5
F6      5.5        0.5
G5     7.25      0.5
B5     7.25      1.0
D#6  8.5        0.5

Here is my code:
    let midi = MidiData()
    if let data = try? Data(contentsOf: URL(fileURLWithPath: file)) {

      midi.load(data: data)

      for track in midi.noteTracks {
        if track.notes.count == 0 {
          continue
        }

        for note in track.notes {
          print(converToNoteName(note.pitch),note.timeStamp,note.duration)
        }
      }
    }

What could be wrong? Thanks.

I think the calculation for time stamp and duration does not consider the tempo.


Add exposure and focus lock functionality

Many camera applications support the ability to press a point in the compose photo frame to spot focus and meter.
If the user presses and holds however, the exposure and focus can be locked, and prevent any automatic focus or exposure controls until the user taps to focus, or takes a picture.
It would be useful for the Camera App to provide mechanism to nominate a spot focus and exposure point, and locking it.

Hey @snrkl,
I'll need to check if CameraX supports this and just in case if it does then I'll soon implement it 👍
Thanks a lot for making this feature request!

Hey @snrkl,
Focus lock can be achieved by setting the focus timeout to Off/0... For exposure lock, the UI is ready, just need to figure out a way to actually implement it via CameraX. If it's possible to implement this, this option should be visible in v8.
Thanks a lot for making this feature request!

That will also lock exposure and white balance since tap to focus does auto focus + auto exposure + auto white balance, not just focus.

Hey @snrkl,
CameraX currently doesn't directly offer support for exposure/white-balance lock, so we might need to wait for a while before they actually support.


The mouse did not enter the box, but an event occurs.

Connect to "https://www.chartjs.org/chartjs-plugin-annotation/latest/samples/interaction/interaction.html"

On the "Config" tab, add "interaction: {intersect: false}", within "options".

Try triggering a mouse event on the chart above.

The mouse did not enter the box, but an event occurs.

I need "interaction: { mode: 'index', intersect: false }" option to my page.
Is there any way to change the option of "interaction" in "chartjs-plugin-annotation" separately?
For example
new Chart(document.getElementById('dataChart'), {   type: 'line',   data: { labels: labels, datasets: datasets },   options: {     ...     interaction: { mode: 'index', intersect: false },     ...     annotation: {         {           type: "box"           , interaction: { intersect: true }, // like this           , xMin: 10           , xMax: 15           , backgroundColor: "rgba(255, 0, 0, 0.3)"           , borderWidth: 0           , click: (({element})=>{             ...           })           , enter: (({element})=>{             ...             return true;           })           , leave: (({element})=>{             ...             return true;           })         }       ]     } });

@feents the interaction can be set at plugin level and used only for annotations. See the documentation: https://www.chartjs.org/chartjs-plugin-annotation/latest/guide/configuration.html
Anyway interaction config cannot be set at annotation level (as you wrote above) but at plugin one and used for all annotations.
You updated code:
new Chart(document.getElementById('dataChart'), {
  type: 'line',
  data: { labels: labels, datasets: datasets },
  options: {
    ...
    interaction: { mode: 'index', intersect: false },
    ...
    annotation: {
      interaction: { intersect: true }, // at plugin level
      annotations: [{
        type: "box"
        , xMin: 10
        , xMax: 15
        , backgroundColor: "rgba(255, 0, 0, 0.3)"
        , borderWidth: 0
        , click: (({element})=>{
          ...
        })
        , enter: (({element})=>{
          ...
          return true;
        })
        , leave: (({element})=>{
          ...
          return true;
        })
      }
    ]}
  }
});

Thank you.
It works for me.

Glad to hear that!


treewide: add targetPrefix to hardcoded references to CC=cc

Motivation for this change
While working on fixing cross-compilation of some packages, I noticed that over and over I had to replace CC=cc with CC=${stdenv.cc.targetPrefix}cc so that it would use the cross-compiler. I have made this change treewide.
Should not affect build -> build compilation since the prefix becomes the empty string.
Replicate with
$ find pkgs -type f -name '*nix' | xargs sed -i '' 's/CXX=c\+\+/CXX=\$\{stdenv\.cc\.targetPrefix\}c\+\+/g'
$ find pkgs -type f -name '*nix' | xargs sed -i '' 's/LD=cc/LD=\$\{stdenv\.cc\.targetPrefix\}cc/g'
$ find pkgs -type f -name '*nix' | xargs sed -i '' 's/CC=cc/CC=\$\{stdenv\.cc\.targetPrefix\}cc/g'

Things done

[ ] Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
Built on platform(s)

[ ] NixOS
[ ] macOS
[ ] other Linux distributions

[ ] Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
[ ] Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
[ ] Tested execution of all binary files (usually in ./result/bin/)
[ ] Determined the impact on package closure size (by running nix path-info -S before and after)
[ ] Ensured that relevant documentation is up to date
[ ] Fits CONTRIBUTING.md.

Due to the small number of rebuilds, I think it is OK to re-do this change to master.

maybe also useful for nixpkgs-hammering? https://github.com/jtojnar/nixpkgs-hammering

maybe also useful for nixpkgs-hammering? jtojnar/nixpkgs-hammering

@jtojnar @rmcgibbo

@siraben: Can you file an issue on hammering so this doesn't get lost?

@siraben: Can you file an issue on hammering so this doesn't get lost?

I am doing that.

What about "AR=${stdenv.cc.targetPrefix}ar"?

What about AR=${stdenv.cc.targetPrefix}ar, ${stdenv.cc.targetPrefix}strip, ${stdenv.cc.targetPrefix}ranlib ?

Addressed.

This is a semi-automatic executed nixpkgs-review with nixpkgs-review-checks extension. It is checked by a human on a best effort basis and does not build all packages (e.g. lumo, tensorflow or pytorch).
If you have any questions or problems please reach out to SuperSandro2000 on IRC.
Result of nixpkgs-review pr 113295 run on x86_64-linux 1

6 packages built:

apg
boxes
hactool
haproxy
micronucleus
mosml

The following issues got detected with the above build packages.
Please fix at least the ones listed with your changed packages:

apg:

configurePhase should probably contain runHook preConfigure and runHook postConfigure.
Near pkgs/tools/security/apg/default.nix:8:3:
  |
8 |   configurePhase = ''
  |   ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/missing-phase-hooks.md
Please add a comment on the line above, explaining the purpose of this patch.
Near pkgs/tools/security/apg/default.nix:14:5:
   |
14 |     ./apg.patch
   |     ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/missing-patch-comment.md
Please add a comment on the line above, explaining the purpose of this patch.
Near pkgs/tools/security/apg/default.nix:15:5:
   |
15 |     ./phony-install-target.patch
   |     ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/missing-patch-comment.md

boxes:

gpl2 is a deprecated license, check if project uses gpl2Plus or gpl2Only and change meta.license accordingly.
Near pkgs/tools/text/boxes/default.nix:43:5:
   |
43 |     license = licenses.gpl2;
   |     ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/unclear-gpl.md
installPhase should probably contain runHook preInstall and runHook postInstall.
Near pkgs/tools/text/boxes/default.nix:30:3:
   |
30 |   installPhase = ''
   |   ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/missing-phase-hooks.md

hactool:

installPhase should probably contain runHook preInstall and runHook postInstall.
Near pkgs/tools/compression/hactool/default.nix:20:3:
   |
20 |   installPhase = ''
   |   ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/missing-phase-hooks.md

haproxy:

gpl2 is a deprecated license, check if project uses gpl2Plus or gpl2Only and change meta.license accordingly.
Near pkgs/tools/networking/haproxy/default.nix:67:5:
   |
67 |     license = licenses.gpl2;
   |     ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/unclear-gpl.md

micronucleus:

gpl3 is a deprecated license, check if project uses gpl3Plus or gpl3Only and change meta.license accordingly.
Near pkgs/development/tools/misc/micronucleus/default.nix:32:5:
   |
32 |     license = licenses.gpl3;
   |     ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/unclear-gpl.md
installPhase should probably contain runHook preInstall and runHook postInstall.
Near pkgs/development/tools/misc/micronucleus/default.nix:22:3:
   |
22 |   installPhase = ''
   |   ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/missing-phase-hooks.md

mosml:

gpl2 is a deprecated license, check if project uses gpl2Plus or gpl2Only and change meta.license accordingly.
Near pkgs/development/compilers/mosml/default.nix:25:5:
   |
25 |     license = licenses.gpl2;
   |     ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/unclear-gpl.md
perl is a build tool so it likely goes to nativeBuildInputs, not buildInputs.
Near pkgs/development/compilers/mosml/default.nix:7:3:
  |
7 |   buildInputs = [ gmp perl ];
  |   ^

See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/build-tools-in-build-inputs.md


Premature DSO unload with "suicidal" continuations

Fixed a problem with premature plugin DSO unloading
when the following conditions are met:

if a continuation created from inside a plugin outlives the
last configuration object that used it and becomes the last
object relying on the plugin DSO
if the continuation event handler logic decides to destroy its
own continuation with TSContDestroy()

then the plugin DSO would get unloaded immediately before the
event handler function reaches its end.

Cherry-picked to v9.0.x branch.


Re assign parser does not handle assignment to indicies

reassignment can handle x = 1
but, it can't handle something like x[0] = 1 or x[some_var] = 1 as of yet
This should be added.

reassign parser should limit chaining of methods / functions. Or, it might be better to make them illegal
so a.b().c() is a compile error
Only a.b() should be allowed, as developers tend to abuse method calls, and produce long "dot chains"
This would be cleaner, and make the code grow vertically, instead of horizontally.

README is empty,  first add reasons for language, and some syntax examples.

Done


UnlockCharger Giving Error

I am a super noob with Python so very well could be an issue on my end.   Please see below, and let me know if I need to provide anything else.
My script outputs the result of the line below correctly so I believe the unlock should work.

"print(f"Charger {charger_id} lock status {chargerStatus['config_data']['locked']}")"

If I add the line below to my script, I get errors.  I've pasted them below.

w.unlockCharger(charger_id)

##############################################
Traceback (most recent call last):
File "", line 1, in
File "C:\Users\josep\AppData\Roaming\Python\Python310\site-packages\wallbox\wallbox.py", line 108, in unlockCharger
raise (err)
File "C:\Users\josep\AppData\Roaming\Python\Python310\site-packages\wallbox\wallbox.py", line 106, in unlockCharger
response.raise_for_status()
File "C:\Users\josep\AppData\Roaming\Python\Python310\site-packages\requests\models.py", line 1024, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://api.wall-box.com/v2/charger/****** <-actual ID is here
##############################################

It looks like you are not authenticated, can you please share the code you are using to unlock the charger (please don't forget to redact your credentials - username and password)
If you want, you can use the test script provided in this repo example-get-chargers.py, not forgetting to set the environment variables with your crendentials
export<EMAIL_ADDRESS>export WALLBOX_PASS="your-password"
python3 example-get-chargers.py

Hmm, that's interesting, an authentication error would need to return a 401 instead of 403.
The code you're using looks good to me (works on my machine :) ) so I don't see any reason not to work for you. But there may be a problem that's not showing up on my side.
Can you check a few things for:

do you have more than 1 EV charger in your account?
what is the charger model you are trying to set?
can you please check the  OCPP settings in the app (is OCPP Enabled)?
does unlock work well in the app? I assume so ..

It's definitely something worth looking into as the 403 behavior is strange. May also be a sign of some restrictions on the Wallbox side, maybe some throttling of sorts.
Thanks!

Again thanks for the quick response!
It is working now.  The account I was using was a "user" account.  I made the account an "admin" account and now it works.  I'm using multiple accounts to track the charging of more than one vehicle for two people.  It is odd that the unlock works in the app with the "user" account but apparently not through the API with a "user" account.
Thank you for the help and the Python module.

do you have more than 1 EV charger in your account? -- No, just 1
what is the charger model you are trying to set? -- Pulsar Plus
can you please check the OCPP settings in the app (is OCPP Enabled)?  -- It is not enabled
does unlock work well in the app? I assume so .. -- It does work in the app.

Ha, good catch, makes sense. Wallbox's user manual seems to suggest that regular users have only access to statistics.
Thanks for sharing this here.


Change version to 1.1.1

Issue #, if available:
Description of changes:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

LGTM. If you havent already, please test  via the CICD deploy once before merging in


Add Google.Type.Money to gax-dotnet

@jskeet, as indicated in #266 we are opening a PR for Google.Type.Money. Please let us know if you have need of additional support from our end. Thank you!

@jskeet, after having consulted with @nycdotnet, I went ahead and implemented your suggested modifications. Please let us know if these changes are sufficient or if you find that further amendments are warranted. Thank you!

@jskeet , please see c4d6ac9.

Great, thanks - merging now.

Thanks @jskeet!

Hi @jskeet we're updating our dependencies and it seems this hasn't been released yet ( DecimalValue feature on Google.Type.Money).  The latest version of Google.Api.CommonProtos on NuGet is still 1.3 from June 4.  I know I explicitly said there is no urgency in #259, but it's been a few months.  Any chance we can get this new version released?
Our sincere thanks for all you do!!

Will try to do this next week - thanks for the reminder :)

Amazing - thanks.

Thanks @jskeet!

Now released in Google.Api.CommonProtos 1.4.0 :)

Thanks so much.


Duplicate symbols

I'm installing version 5.2.0 using cocoapods in Xcode 6.4 and I'm getting a duplicate symbols error when linking.
Reproducing is simple:

create a new XCode project with Deployment Target set to 7.0
pod init
Add CardIO 5.2.0 to the Podfile and pod install
Build project

Probably a duplicate of #148, or at least the same underlying fix.

You will need to use Xcode 7 with any Bitcode enabled library.


terrain example not working

The terrain example is not working (perhaps due to outdated API call?):
matter.js:7486 Uncaught TypeError: path.getPathSegAtLength is not a function
at Object.Svg.pathToVertices (matter.js:7486)
at SVGPathElement. (terrain.js:43)
at Function.each (jquery-3.1.1.js:368)
at jQuery.fn.init.each (jquery-3.1.1.js:157)
at Object. (terrain.js:42)
at fire (jquery-3.1.1.js:3305)
at Object.fireWith [as resolveWith] (jquery-3.1.1.js:3435)
at done (jquery-3.1.1.js:9242)
at XMLHttpRequest. (jquery-3.1.1.js:9484)

The solution is to use the latest version of pathseg rather than the one used in the examples. I'll get it updated in the examples soon.

So do SVGs work with matter.js?
If so, can someone point me to the right direction b/c I have been looking into this for like 2.5 hours

Check out the SVG example, though support is basic and more a proof of concept than anything. If you need something more, the general idea is to cut the shape into convex parts to form a compound body.


Get the jobs in last N days need tuning

I don't find a easy way to get the jobs in last N days need tuning

I find it in search .....


Do not skip root tree when searching for trees

This fixes an issue where restic cannot find the tree when trying to find the tree id of a snapshot.

What does this PR change? What problem does it solve?
restic find --tree <id> cannot find the tree referenced by restic snapshot --json since it skips the root tree when searching.
Was the change previously discussed in an issue or on the forum?

Checklist

[x] I have added tests for all code changes.
[ ] I have added documentation for relevant changes (in the manual).
[x] There's a new file in changelog/unreleased/ that describes the changes for our users (see template).
[x] I'm done! This pull request is ready for review.

The linter is still unhappy:

cmd/restic/cmd_find_integration_test.go:94: File is not gofmt-ed with -s (gofmt)


Rename "Images" dirs to "XCAssets"

➡ Part 1 of SwiftGen/SwiftGen/issues/311
⬜ Part 2 here
⬜ Part 3 here

@djbe 3 of your 4 points should be addressed now. I'll let you update the references in the README (good occasion to re-read it and see if it's up-to-date :wink😃 while I re-align the other PRs accordingly.


Add 3D

An ellipse could exist in 3D too. Would be cool to add a method for that.

I don't know a method for that, but maybe this can be done by rotating the 3D data into a 2D plane.
This would make the algorithms reusable.

That is indeed a general strategy: Use the SVD decomposition (very close to performing a PrincipalComponentDecomposition, or PCA)  to determine a normal to the plane in which you have your circle, project the points onto that plane, and use a 2D algorithm. There are however also algorithms that do this for 3D directly.
I am writing here because I am doing a master project, and a fellow student that sits right next to me is working on implementing all kinds of circle fitting algorithms. Some are 2D, some are 3D, but all are intended to work on 3D data. I was just wondering: is this package open to PRs implementing new methods? And before I potentially get to that, I was also wondering: The current API and the examples in the readme seem less-than-ideal to me. If I start implementing such algorithms, would this package be open to reworking the API, revamping the readme, and making a proper documentation page? All in all, the "look and feel" of the package might come out with significant differences.
Further discussion about details is probably best to have in specific pull-requests, e.g. one for API, one for documentation, and one for each new algorithm. But before I start such efforts, I just wanted to check: Is there appetite for such changes?

Contributions are always welcome!
Regarding the API the initial one was just a collection of functions. I tried to get them into a more streamlined version by looking at other fitting packages. Which resulted in methods like fit or coef. If a new API is required we can for sure adapt and maybe extend the old one to keep it compatible with older code.
More documentation would also be great.
As there were not that many methods fully implemented/optimized I just made a Readme, but this can be extended to a documenter.jl page for sure.

That sounds very good to my ears, and I am finding your reply quite encouraging! I am thinking that using StatsAPI.jl, defining methods for fit, and setting the algorithm as a type (similar to sol = solve(prob, NewtonRaphson()) from SciML's NonlinearSolve.jl) would be a good way to go. I am not 100% sure, but aligning the API with some of the major Julia packages can hardly be a bad idea.
I will see if I get around to it. In the worst case, I expect to at least just provide the functions in their current form to this package. In the best case, I will make PRs for an API rework, new algorithms, and a Documenter.jl page ^_^

Sounds good to me. :) I already added a setup for the Documenter.jl page yesterday.
https://feanor12.github.io/CircleFit.jl/dev/

Very nice! I can see that I am hard-pressed for time, and will be unlikely to make progress on this in the near future. But it is not forgotten!

My project is now concluded. I have some other personal business in the upcoming time, and I am not at all certain I will find time for this any time soon. But I just spent an hour translating the method based on conformal geometric algebra (CGA), so that at least a minimal working implementation will come from this. The following code is coarsely translated from python, and no effort has been put into aligning the UI with this package.
using LinearAlgebra

# Simplified helper function to extract parameters from the multivector
function extract_mv_parameters2(mv::Vector{<:Real})
    cvx, cvy, cvz = mv[1:3]   # e2^e3, e3^e1, e1^e2
    cgx, cgy, cgz = mv[4:6]   # e0^e1, e0^e2, e0^e3
    cmx, cmy, cmz = mv[7:9]   # e1^einf, e2^einf, e3^einf
    cgw = -mv[10]             # e0^einf

    num = cvx^2 + cvy^2 + cvz^2 - cgw^2 + 2 * (cgx * cmx + cgy * cmy + cgz * cmz)
    denom = cgx^2 + cgy^2 + cgz^2
    r = sqrt(num / denom)

    n = -[cgx, cgy, cgz]
    nn = n / norm(n)

    B = [cgw -cvz cvy; cvz cgw -cvx; -cvy cvx cgw]
    c = (B * n) / sum(n .^ 2)

    return c, nn, r
end

# Main function to fit a circle in 3D space using CGA
"""
Takes in points in 3D space and outputs a fitted circle in 3D based on a method in Conformal Geometric Algebra (CGA).

    Input is points in 3D euclidean space with each row being a point, and each column is the xyz coordinate.
    The ouput is: centrum, radius, normal_vector
    where circle_cga is the CGA representation of the fitted circle, in the IPNS representation!

    This method is solved by calculating the stacked matrix: M_stacked, which is solved with SVD.

    Example usage:
    >>> centrum, radius, normal_vector, circle_cga = circlefitCGA3D(points)
"""
function circlefitCGA3D(points)
    N = size(points, 1)
    M_stacked = zeros(Float64, 5 * N, 10)

    for i in 1:N
        x4 = 0.5 * sum(points[i, :] .^ 2)

        px, py, pz = points[i, :]
        vec_cross = [0 -pz py; pz 0 -px; -py px 0]

        Mi = [
            -vec_cross  -x4 * I(3)  I(3)  zeros(3, 1);
            zeros(1, 3)  -points[i, :]'  zeros(1, 3)  1;
            zeros(1, 3)  zeros(1, 3)  points[i, :]'  -x4
        ]

        M_stacked[5*(i-1)+1:5*i, :] = Mi
    end

    V = svd(M_stacked, full=false).V
    circle_og = V[:, end]

    return extract_mv_parameters2(circle_og)
end

# Wrapper function to accept separate x, y, z vectors
circlefitCGA3D(xs, ys, zs) = circlefitCGA3D(hcat(xs, ys, zs))

Some code for testing the function

"""
Generates points on a circle in 3D and outputs the 3D euclidean coordinates of the generated points.

The function takes in a normal vector, which expresses the direction of the circle, meaning the direction of the plane the circle lies in,
    radius of the circle, offsets to displace the circle center in 3D, how many points are to be generated, and how large the random noise to be added is.
    The output is a matrix of size num_points x 3, with the format:
    [[x1, y1, z1],
    [x2, y2, z2],
    [x3, y3, z3]...]

    The noise is independent Gaussian noise on the x, y, and z-coordinate.

    Example usage:
    >>> circle_points = generate_circle_points([1.0, 1.0, 1.0], 2.0, [1.0, 1.0, 1.0], 100, 0.05)
"""
    function generate_circle_points(normal_vector::Vector{<:Real}, radius::Real, offsets::Vector{<:Real}, num_points::Integer, noise_scale::Real)
    # Generate points on a 2D circle
    theta = range(0, stop=2π*(num_points-1)/num_points, length=num_points)
    x_circle = radius * cos.(theta)
    y_circle = radius * sin.(theta)

    # Normalize the normal vector
    normal_vector /= norm(normal_vector)

    # Calculate the axis-angle representation for rotation
    # Reference: https://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle
    angle = acos(normal_vector[3])  # Angle between z-axis and normal vector
    axis = cross([0.0, 0.0, 1.0], normal_vector)  # Axis of rotation
    axis /= norm(axis)

    # Rotation matrix
    c = cos(angle)
    s = sin(angle)
    t = 1 - c
    rotation_matrix = [
        t*axis[1]^2 + c                 t*axis[1]*axis[2] - s*axis[3]   t*axis[1]*axis[3] + s*axis[2]
        t*axis[1]*axis[2] + s*axis[3]   t*axis[2]^2 + c                 t*axis[2]*axis[3] - s*axis[1]
        t*axis[1]*axis[3] - s*axis[2]   t*axis[2]*axis[3] + s*axis[1]   t*axis[3]^2 + c
    ]

    # Rotate points to align with the specified normal vector
    rotated_points = rotation_matrix * hcat(x_circle, y_circle, zeros(num_points))'
    x_circle, y_circle, z_circle = rotated_points[1, :], rotated_points[2, :], rotated_points[3, :]

    # Set random seed for reproducibility of 'random' noise. Can be commented out.
    # Random.seed!(42)

    # Add noise to the points and the constant offset
    x_circle += randn(num_points) * noise_scale .+ offsets[1]
    y_circle += randn(num_points) * noise_scale .+ offsets[2]
    z_circle += randn(num_points) * noise_scale .+ offsets[3]

    return hcat(x_circle, y_circle, z_circle)
end

let
    # Example usage
    normal_vector = [1, 1, 1]  # Normal vector
    radius_og = 1
    num_points = 100
    offsets = [1, -1, 0.25]

    noise_scale = 0.05
    points = generate_circle_points(normal_vector, radius_og, offsets, num_points, noise_scale)

    # 'Default method for circle fitting, which is SVD on M_stacked
    # centrum, radius, normal_vector = circlefitCGA3D(points)
    centrum, normal_vector, radius = circlefitCGA3D(points)
    @show radius
    @show centrum
    @show normal_vector
end

Very nice! Do you want to provide the pull request?
In case, you are ok with adding your code I can also generate a pull request.

Feel free to add it - this is rather far back on my priority list right now, so it would have been a while before I got to it xD


rotates do not appear to work.

I've tried making the simplest example with rotate and can't get to the bottom of why it's not working.
rotate* types expect a number, though I'm not sure what that number maps to. Degrees? Radians?
<Motion.View
  animate={{ rotate: 90 }}
  initial={{ rotate: 0 }}
  transition={{
    type: "timing",
    duration: 2000
  }}
  style={{ borderWidth: 1, height: 50, width: 50 }}
/>

Results in a box that just sits there, statically. I can verify that other transforms, like x and y work, but not any of the rotations.

Things that may matter:

using react-native-web
using this for components that run on native and the browser

Thanks for catching that! Fixed in 2.1.8.
You're right, it should not be a number. It should match the Animated values, so 90deg or 1.57rad. It was previously mis-typed as number and not passing interpolated values into transforms. So now it should interpolate the deg and rad strings correctly.

That's great. I didn't get a chance to add an issue, but my colleague and I noticed that skews also did not appear to do anything. I'll give 2.1.8 a try today and see if that has resolved as well.

Yes, skews should also be fixed by that change too. I just released a 2.1.9 that fixes the types for skews.

Thank you for the quick responses. It is appreciated!


light.turn_on not working when using specific red

Home Assistant release (hass --version):
0.58.1
Python release (python3 --version):
3
Component/platform:
z-wave / light
Description of problem:
I am automating my Aeon Labs LED strip using this:
- alias: Hallway upstairs - turn led to red during night
  trigger:
    - platform: state
      entity_id: sensor.hallway_upstairs_multisensor_burglar
      to: '8'
    - platform: numeric_state
      entity_id: sensor.hallway_upstairs_multisensor_luminance
      below: '60'
  condition:
    condition: and
    conditions:
      - condition: numeric_state
        entity_id: sensor.hallway_upstairs_multisensor_luminance
        below: '60'
      - condition: time
        after: '22:00'
        before: '7:00'
  action:
    - service: light.turn_on
      entity_id: light.hallway_upstairs_ledstrip_level
      data:
        brightness_pct: '50'
        rgb_color: [40,255,50]
#        color_name: 'red'

#============================================================

- alias: Hallway upstairs - turn led to bright during day
  trigger:
    - platform: state
      entity_id: sensor.hallway_upstairs_multisensor_burglar
      to: '8'
    - platform: numeric_state
      entity_id: sensor.hallway_upstairs_multisensor_luminance
      below: '60'
  condition:
    condition: and
    conditions:
      - condition: numeric_state
        entity_id: sensor.hallway_upstairs_multisensor_luminance
        below: '60'
      - condition: time
        after: '7:00'
        before: '22:00'
  action:
    - service: light.turn_on
      entity_id: light.hallway_upstairs_ledstrip_level
      data:
        brightness_pct: '70'
        kelvin: '2700'
#        color_name: 'red'

#============================================================

- alias: Hallway upstairs - turn off led at night
  trigger:
    - platform: state
      entity_id: sensor.hallway_upstairs_multisensor_burglar
      to: '0'
      for:
        minutes: 5
  condition:
    condition: and
    conditions:
      - condition: time
        after: '22:00'
        before: '7:00'
  action:
    - service: light.turn_off
      entity_id: light.hallway_upstairs_ledstrip_level

As you can see, I am trying to use some sort of red during the night whenever I need to roam around in the hallway. However, the LED doesn't take the right form of light:

[255, 0, 0] => red
[255, 100, 100] => white
[100, 0, 0] => white
[0, 255, 0] => green
[0, 125, 0] => light green

I can basically combine anything, as long as I leave the red either 0 or 255. If not, the light will always fall back to white.
Expected:
I would expect to be able to use any color.

Doing some additional testing. Looks like as long as I only set 2 of 3 values (so keep at least 1 in the array to 0), it sets a color.

Using css 'crimson' also sets the LED strip to white. Could this be a bug in HA or is this a LED strip issue?

Looks like the latest release (0.66.0) has changed something (colors are now a bit different). Probably related to #13360 which was caused by wrong parameter types.


Not able to parse official Microsoft XLSX/DOCX/PPTX files with LlamaParseReader

Referring to packages/llamaindex/src/readers/LlamaParseReader.ts. It uses the magic number of the file to detect the file type before sending it to LlamaParse cloud. Microsoft Office files (pptx, xlsx, docx) are technically application/zip, and not application/vnd.openxmlformats-officedocument.wordprocessingml.document as the LlamaParseReader class expects, and therefore throws an error.
File has type \"application/zip\" which does not match supported MIME Types. Supported formats include: .pdf, .602, .abw,...

could you please give a example file to test?

Yup, any xlsx file created through Microsoft Excel, like the one attached. You can see it with the Magic-bytes.js playground here: https://larskoelpin.github.io/magic-bytes/

test.xlsx


docs: Add interactive example for Anchor

Description
This PR add an interactive example to show the parent child relationship when their anchors are changed. It also elaborates the same in written docs as well.
https://user-images.githubusercontent.com/33748002/235361268-7636d25c-5c07-4124-9ce5-de9485b0fb1b.mp4
Checklist

[x] I have followed the [Contributor Guide] when preparing my PR.
[-] I have updated/added tests for ALL new/updated/fixed functionality.
[x] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
[x] I have updated/added relevant examples in examples or docs.

Breaking Change?

[ ] Yes, this PR is a breaking change.
[x] No, this PR is not a breaking change.

Related Issues
Closes #2510

Looks good! Maybe it could be good to clarify that the position is 0,0 for the child?

Should I updated that in the infobox comment under the example?

Should I updated that in the infobox comment under the example?

Wherever you think it looks the best :)