I tried something new this weekend and created a Unity integration with my C2 ergometer. I was following the approach that I wrote about a few months ago:
For my test-integration I used this script to generate some Bots and (a simulated) player. I then learned the basics of Unity to connect some sort of generic 3D application to show what the boats are doing.
I uploaded the Unity project to Github too, it has some nice features integrated and I’m planning on extending it in the future.
I called the communication layer Fitznet – there’s Fitness and Network in there I guess. The protocol is based on Google Protobuf, I also created a small ZMQ Forwarder to keep the set up easy. Currently the whole thing is in an early development phase and I’m not sure if it will ever leave this state. But there’s some potential in there I think, perhaps if the right people are working on it…
Here’s a video of the current progress:
I just ran into a very strange problem that almost caused me to reinstall my OS:
I installed QtCreator with a MinGW toolset fresh from the Qt-Homepage. Everything worked as expected and I created an empty Hello World project to test things out. From then on it got ugly: When starting the project QtCreator froze and I wasn’t able to delete the generated .exe file.
I did some research and found nothing of help. There were some issues with early Windows 10 builds or some users having incorrect runtime environments. In the end it turned out that the issue was caused by Avast 2015 – It blocked all Qt-based executables, whether they’re started by QtCreator or directly.
I turned off active filesystem search and was able to use my executable. Hope this helps someone out there experiencing the same issue.
Epic Games recently announced that their Unreal Engine is available for free now. There are certain limitations when using it commercially, but these are far from being a limitation.
During the day I watched a lot of videos on the Epic Youtube-Channel, I also tried a few different things and discovered /r/unrealengine on reddit. I’m very fascinated by how complex, but well-thought the software is. I’ve rarely seen something big like that which also seems to simply work. I’m still working on getting a general overview to see the whole potential.
Perhaps it’d be worth it to remake DynRow in the Unreal Engine? There would be a lot of advantages I could see right now, like being able to support multiplatforms out of the box (Windows, Android, iOS, …) or having all these mighty tools in the background to help me developing it. Of course it would be perfect to have such high fidelity graphics available. What about a rowing simulation with VR support?
I’m hyped, let’s see what’ll be possible.
DynRow now records the users workout-data to a SQLite database during the session. This has several advantages:
- Ghost Bot: This one is already implemented. There is a new Bot available which is able to read the SQLite data and apply it. The result is an opponent which rows exactly like the user rowed during a previous workout
- Share workout: This is kind of related to the Ghost Bot. Users are now able to share their saved workouts with others. This means that it is possible to row against your rowing buddies or athletes you want to compete with
- Better testing: I’m currently just creating data on the fly when no erg is connected. Though this is a good way to test the basic functionality it is always better to have real-life testing data. By being able to integrate previous workouts as a way to test it is now possible to easily reproduce certain bugs
- Statistics: A workout application without the ability to generate complex statistics is not really exciting. By recording everything the user does during workout the foundation of generating statistics is now laid
One thing is also a bit related, but’ll need a bit more work to get it running: The ability to share the rowing data online during the workout. This would essentially allow to row against others in realtime over the internet. This feature is not planned as of yet, but it won’t be impossible to realize.
I fixed a lot of different issues with DynRow in the last days, but one feature stands out: I created Boomerang Bots. These bots are rowing with a constant pace until they get out of a certain range. Then they’ll reduce or increase speed to stay near the player.
This way it is possible to have different bots around the player for the entire exercise. This adresses one of the bigger problems I had with the available rowing software: I set up an opponent with a certain speed. In the beginning of the workout the opponent stayed near the boat and was a good motivation to keep going. Sometime during my workout however I was able to row faster than the bot or the bot was rowing away – I was basically rowing on my own for the rest of the time.
Boomerang Bots forgive smaller pauses the player does, they also keep up when the player has a good day and is rowing faster than expected.
Here’s a video I made: Youtube
So what’s next? I started refactoring the inner working and will do that primarily during the next days. I also want to make everything more user-friendly. Currently there’s no starting screen and the user needs to alter the code to set up his workout.
As part of the project a software developer should always “Eat his own dog foot”: test and use the application that is being developed. It’s important to know how your own product works and feels. Usually this is not a big deal, every now and then it is needed to run the code and test if everything works as expected. With DynRow it wasn’t that easy: I’m currently injured on my knee, so it’s not possible for me to get on the ergometer and just row away while DynRow runs in the background.
I was able to test the application with testing data – The player data did not come from the ergometer but from a generic input which generated a constant pace. However when I first sat down on my ergo a few days ago and actually tested the application, it was a whole other thing: Testing data did not show that for example certain statistics were too small to see them while in motion. Testing data also did not show that the currently implemented bots do not work very well when actually rowing against them.
What I did was to row with a very low intensity, just so my knee could handle it. I then put my phone beside me during the training session and everytime I noticed something I paused and noted it down. One of the first things I wrote down was that the application does not automatically Pause when the user interrupts his workout, so there’s that… I assembled a list of around 20 issues which I afterwards rethought and created about 15 Github issues from.
Now I have a bigger list of things that I could fix and implement. The first iteration worked good: I fixed some of the bigger issues yesterday and tried DynRow afterwards: It improved a lot and felt actually quite good to use. It’s not that good that I would actively promote it for others to use, but it’s making progress. Now I only have to heal up my knee so I can do some more intense testing (and also be able to get my fitness level up again).
The design of DynRow is quite simple and follows that of almost every game engine: There’s a loop running for the lifetime of the program. In every cycle the same steps are done:
- Get the newest data from the Concept 2
- Update the AI boats
- Visualize the latest available data
Let’s just jump into these steps to get an overview:
Get data from the Concept 2: This is where PyRow is used. I created a static class called ErgStats which wraps around the PyRow-API. This way I’m not depending on PyRow everywhere in my application and I can easily swap it out if needed. A more object oriented way would be to create some sort of dependency injection here, that way I could more easily switch between generating test data and using the real data. Currently I implemented a quick hack where I used a try/catch when importing PyRow. If it fails to import I fall back to test data.
Update the AI: I created a PlayGround-class which holds a list of all the boats in the simulation. All boats get updated every cycle. The current logic implementation allows it to have different types of boats available, I just implemented a constant rowing boat and a very simple rubberband boat for now, but there’s potential to have more complex boats integrated.
Visualize everything: At first I used the TKInter Canvas because I wanted to use as less thirdparty software as possible. Python brings lot’s of stuff, so I thought it isn’t really needed to integrate more stuff from external repositories. My targeted hardware specification caused me to rethink this approach: I want DynRow to run on very basic hardware, at best it could be used on something simple like a Raspberry Pi. TKInter.Canvas, or at least the way I used it, is not very performant. After struggling a bit I added PyGame to the mix, which also provides some easy to use Gameloop-mechanics. My current implementation isn’t as optimized as it could be, but I’m quite happy with the resulting look and performance.
That’s almost everything you need to know. I wanted to keep the program as simple as possible, my primary focus was on creating a usable prototype as early as possible.